[gcjx] Patch: FYI: gcjx CNI fixes

Tom Tromey tromey@redhat.com
Mon Apr 4 04:26:00 GMT 2005


I'm checking this in on the gcjx branch.

This updates the gcjx CNI header generator to emit __align__
attributes as needed.  It also adds command line options for
inserting text into the generated header.

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	* main.cc (argument_parser::action_class): New field.
	(argument_parser::cni_generator): Likewise.
	(argument_parser): Initialize new field.
	(argument_parser::need_cni_generator): New method.
	(argument_parser::need_cni_class): Likewise.
	(argument_parser::parse_args): Set cni_generator.  Recognize new
	arguments.
	(argument_parser::help_options): Document new options.
	* header/cni.hh (cni_code_generator::write_field): Updated.
	(cni_code_generator::action): New enum.
	(cni_code_generator::add_action): Declare.
	(cni_code_generator::action_item_list): New typedef.
	(cni_code_generator::action_map): New field.
	(cni_code_generator::empty_list): Likewise.
	(cni_code_generator:emit_actions): Declare.
	(cni_code_generator::action_map_type): New typedef.
	* header/cni.cc (write_field): Added 'is_first' argument.
	(generate): Updated.  Call emit_actions.
	(emit_actions): New method.
	(add_action): Likewise.

Index: main.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/Attic/main.cc,v
retrieving revision 1.1.2.4
diff -u -r1.1.2.4 main.cc
--- main.cc 13 Feb 2005 03:35:02 -0000 1.1.2.4
+++ main.cc 4 Apr 2005 04:25:28 -0000
@@ -104,7 +104,8 @@
 {
 public:
   argument_parser (char *argv[])
-    : comp (global->get_compiler ())
+    : comp (global->get_compiler ()),
+      cni_generator (NULL)
   {
     for (; *argv; ++argv)
       {
@@ -229,7 +230,7 @@
   help_options ()
   {
     std::ostream &os = std::cout;
-    os << "usage: gcjx [OPTIONS] FILE..." << std::endl
+    os << "Usage: gcjx [OPTIONS] FILE..." << std::endl
        << "  A file whose name starts with '@' holds arguments (which can be\n"
        << "  any mix of options and files), separated by either spaces or\n"
        << "  newlines."
@@ -262,6 +263,14 @@
 
     os << std::endl;
 
+    print ("-cniclass CLASS", "set class for CNI text generators", 3);
+    print ("-add TEXT", "print text in class body", 3);
+    print ("-prepend TEXT", "print text before class declaration", 3);
+    print ("-append CLASS", "print text after class declaration", 3);
+    print ("-friend CLASS", "print text in class as friend declaration", 3);
+
+    os << std::endl;
+
     print ("--help", "print help and exit", 3);
     print ("--help-warnings", "print help about warnings and exit", 3);
     print ("--version", "print version and exit", 3);
@@ -363,6 +372,22 @@
     return first.substr (name.length () + (use_equals ? 1 : 0));
   }
 
+  void
+  need_cni_generator (const std::string &name)
+  {
+    if (cni_generator == NULL)
+      throw make_error ("no CNI header generator specified for option %1")
+	% name;
+  }
+
+  void
+  need_cni_class (const std::string &name)
+  {
+    if (action_class.empty ())
+      throw make_error ("no %<-cniclass%> specified for option %1")
+	% name;
+  }
+
   std::deque<std::string>
   parse_args ()
   {
@@ -441,8 +466,11 @@
 	      comp->add_code_generator (new jni_code_generator (comp,
 							        comp->get_directory_cache ()));
 	    else if (otype == "cni")
-	      comp->add_code_generator (new cni_code_generator (comp,
-							        comp->get_directory_cache ()));
+	      {
+		cni_generator = new cni_code_generator (comp,
+							comp->get_directory_cache ());
+		comp->add_code_generator (cni_generator);
+	      }
 	    else if (otype == "jnistub")
 	      comp->add_code_generator (new jni_stub_generator (comp,
 							        comp->get_directory_cache ()));
@@ -475,6 +503,39 @@
 	  help_warnings ();
         else if (arg == "-version" || arg == "--version")
 	  version ();
+	else if (arg == "-cniclass")
+	  {
+	    need_cni_generator ("-cniclass");
+	    action_class = get_arg_for (it, "-cniclass");
+	  }
+	else if (arg == "-add")
+	  {
+	    need_cni_generator ("-add");
+	    cni_generator->add_action (cni_code_generator::CNI_ADD,
+				       action_class,
+				       get_arg_for (it, "-add"));
+	  }
+	else if (arg == "-append")
+	  {
+	    need_cni_generator ("-append");
+	    cni_generator->add_action (cni_code_generator::CNI_APPEND,
+				       action_class,
+				       get_arg_for (it, "-append"));
+	  }
+	else if (arg == "-friend")
+	  {
+	    need_cni_generator ("-friend");
+	    cni_generator->add_action (cni_code_generator::CNI_FRIEND,
+				       action_class,
+				       get_arg_for (it, "-friend"));
+	  }
+	else if (arg == "-prepend")
+	  {
+	    need_cni_generator ("-prepend");
+	    cni_generator->add_action (cni_code_generator::CNI_PREPEND,
+				       action_class,
+				       get_arg_for (it, "-prepend"));
+	  }
         else
 	  die_unrecognized ("option", arg);
       }
@@ -541,6 +602,11 @@
 
   compiler *comp;
   std::deque<std::string> args;
+
+  // The CNI code generator and the current class for which we're
+  // collecting actions.
+  std::string action_class;
+  cni_code_generator *cni_generator;
 };
 
 int
Index: header/cni.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/header/Attic/cni.cc,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 cni.cc
--- header/cni.cc 8 Mar 2005 17:27:37 -0000 1.1.2.2
+++ header/cni.cc 4 Apr 2005 04:25:28 -0000
@@ -30,6 +30,29 @@
 {
 }
 
+void
+cni_code_generator::emit_actions (std::ostream &out,
+				  cni_code_generator::action what,
+				  const action_item_list &items)
+{
+  bool any = false;
+  for (action_item_list::const_iterator i = items.begin ();
+       i != items.end ();
+       ++i)
+    {
+      if ((*i).first != what)
+	continue;
+
+      out << "  ";
+      if (what == CNI_FRIEND)
+	out << "friend ";
+      out << (*i).second << std::endl;
+      any = true;
+    }
+  if (any)
+    out << std::endl;
+}
+
 std::string
 cni_code_generator::cxxname (model_type *type, bool leading)
 {
@@ -359,7 +382,8 @@
 void
 cni_code_generator::write_field (std::ostream &out,
 				 model_field *field,
-				 modifier_t &current_flags)
+				 modifier_t &current_flags,
+				 bool &is_first)
 {
   modifier_t new_flags = field->get_modifiers () & ACC_ACCESS;
   update_modifiers (out, new_flags, current_flags);
@@ -370,10 +394,35 @@
   out << cxxname (field->type ());
   if (! field->type ()->reference_p ())
     out << " ";
+
+  if (is_first && ! field->static_p ())
+    {
+      is_first = false;
+      out << "__attribute__ ((__aligned__ (__alignof ("
+	  << cxxname (field->get_declaring_class ())
+	  << ")))) ";
+    }
+
   out << field->get_name () << ";" << std::endl;
 }
 
 void
+cni_code_generator::add_action (cni_code_generator::action what,
+				const std::string &name,
+				const std::string &text)
+{
+  action_map_type::iterator it = action_map.find (name);
+  if (it == action_map.end ())
+    {
+      action_item_list elt;
+      elt.push_back (std::make_pair (what, text));
+      action_map[name] = elt;
+    }
+  else
+    (*it).second.push_back (std::make_pair (what, text));
+}
+
+void
 cni_code_generator::generate (model_class *klass)
 {
   std::string filename = directories.add (klass, ".h");
@@ -383,6 +432,11 @@
     std::cout << " [writing " << filename << "]" << std::endl;
 
   std::string cname = klass->get_fully_qualified_name ();
+
+  action_map_type::const_iterator it = action_map.find (cname);
+  bool found = it != action_map.end ();
+  const action_item_list &actions (found ? (*it).second : empty_list);
+
   // Ugly...
   for (unsigned int i = 0; i < cname.length (); ++i)
     {
@@ -404,6 +458,8 @@
   write_includes (out, klass, methods.begin (), methods.end (), fields);
   out << std::endl;
 
+  emit_actions (out, CNI_PREPEND, actions);
+
   out << "class " << cxxname (klass, false);
   if (klass->get_superclass ())
     out << " : public ::" << cxxname (klass->get_superclass (), false);
@@ -429,17 +485,24 @@
       write_method (out, (*i).get (), current_flags);
     }
 
+  bool first = true;
   for (std::list<ref_field>::const_iterator i = fields.begin ();
        i != fields.end ();
        ++i)
-    write_field (out, (*i).get (), current_flags);
+    write_field (out, (*i).get (), current_flags, first);
 
   // One final phony field.
   update_modifiers (out, modifier_t (ACC_PUBLIC), current_flags);
+
+  emit_actions (out, CNI_FRIEND, actions);
+  emit_actions (out, CNI_ADD, actions);
+
   out << "  static ::java::lang::Class class$;" << std::endl;
 
   out << "};" << std::endl
       << std::endl;
 
+  emit_actions (out, CNI_APPEND, actions);
+
   out << "#endif // " << cname << std::endl;
 }
Index: header/cni.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/header/Attic/cni.hh,v
retrieving revision 1.1.2.3
diff -u -r1.1.2.3 cni.hh
--- header/cni.hh 8 Mar 2005 17:27:37 -0000 1.1.2.3
+++ header/cni.hh 4 Apr 2005 04:25:28 -0000
@@ -27,13 +27,32 @@
 
 class cni_code_generator : public code_generator
 {
+public:
+
+  /// This type is used when registering a header-modifying action.
+  typedef enum
+  {
+    CNI_ADD,
+    CNI_APPEND,
+    CNI_FRIEND,
+    CNI_PREPEND
+  } action;
+
 protected:
 
+  // Handy typedefs.
+  typedef std::list<model_method *>::const_iterator method_iterator;
+  typedef std::list< std::pair<action, std::string> > action_item_list;
+  typedef std::map<std::string, action_item_list> action_map_type;
+
   // The compiler we're using.
   compiler *comp;
 
-  // Handy typedef.
-  typedef std::list<model_method *>::const_iterator method_iterator;
+  // This maps class names to action items.
+  action_map_type action_map;
+
+  // An empty list that we use as needed.
+  action_item_list empty_list;
 
   std::string cxxname (model_type *, bool = true);
   void update_modifiers (std::ostream &, modifier_t, modifier_t &);
@@ -44,13 +63,14 @@
 		       const method_iterator &, const method_iterator &,
 		       const std::list<ref_field> &);
   void write_method (std::ostream &, model_method *, modifier_t &);
-  void write_field (std::ostream &, model_field *, modifier_t &);
+  void write_field (std::ostream &, model_field *, modifier_t &, bool &);
 
   void indent (std::ostream &, int);
   void open_package (std::ostream &, model_package *, model_package *, int &);
   void move_to_package (std::ostream &, model_package *, model_package *,
 			int &);
   void write_namespaces (std::ostream &, const std::set<model_class *> &);
+  void emit_actions (std::ostream &, action, const action_item_list &);
 
 public:
 
@@ -61,6 +81,12 @@
   /// This is called to generate code for a class and write it.
   void generate (model_class *);	
 
+  /// Add an action of the given type.  NAME is the name of the class
+  /// to which the action applies.  TEXT is the text to emit at the
+  /// indicated position.
+  void add_action (action task, const std::string &name,
+		   const std::string &text);
+
   bool handles_class_p () const
   {
     return true;



More information about the Java-patches mailing list