[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 ¤t_flags)
+ modifier_t ¤t_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