diff mbox

gengtype improvements for plugins, completed! patch 5/N [typedopt]

Message ID 20100911135826.GA24021@hector.lesours
State New
Headers show

Commit Message

Basile Starynkevitch Sept. 11, 2010, 1:58 p.m. UTC
Hello All,

[join work by Basile Starynkevitch & Jeremie Salvucci]

References: 
  http://gcc.gnu.org/ml/gcc-patches/2010-08/msg02060.html
  http://gcc.gnu.org/ml/gcc-patches/2010-09/msg00616.html
  http://gcc.gnu.org/ml/gcc-patches/2010-09/msg00663.html
  http://gcc.gnu.org/ml/gcc-patches/2010-08/msg02063.html
  http://gcc.gnu.org/ml/gcc-patches/2010-08/msg02065.html
  http://gcc.gnu.org/ml/gcc-patches/2010-08/msg02068.html
  http://gcc.gnu.org/ml/gcc-patches/2010-09/msg00983.html

This fifth patch chunk is an improved version of
http://gcc.gnu.org/ml/gcc-patches/2010-08/msg02068.html taking into
account Laurynas comments in
http://gcc.gnu.org/ml/gcc-patches/2010-09/msg00420.html

The major improvment of this "completed!" chunk w.r.t. its previous
version http://gcc.gnu.org/ml/gcc-patches/2010-08/msg02068.html is
mostly that I did add a lot of comments while moving definitions from
old gengtype.c to new gengtype.h; while adding comments slightly
increase the burden of reviewers, it should not change the behavior of
gengtype, and it should hopefully help a lot any future gengtype
hacker.  I hope that adding comments don't decrease the probability of
having this work accepted into GCC 4.6 end of stage 1.

In addition to the improved comments, I made some minor cleanups
w.r.t. http://gcc.gnu.org/ml/gcc-patches/2010-08/msg02068.html (such
as using OPTION_STRING instead of INFO_STRING for the kind of a string
option, etc.).

I also changed the indentation: old gengtype.c had severals 
  struct FOOBAR
  {
while it seems that the preferred indentation style (at least when
looking into gimple.h or tree.h) is instead
  struct FOOBAR {
which I suppose is the politically correct way of GCC coding.

In addition of moving lots of typing definitions from gengtype.c to
gengtype.h I also (and this is already the case in the previous
version http://gcc.gnu.org/ml/gcc-patches/2010-08/msg02068.html of
this patch), and obviously, made the 'struct options' a typed &
discriminated data, because to persist the gengtype state every union
should be a sum type discriminated conveniently.

The attached patch relative to the "completed!" patch 4/N [filesrules]
sent in http://gcc.gnu.org/ml/gcc-patches/2010-09/msg00983.html is
obtained with

diff -u -p  $(svn stat . |awk '/M/{print $2}') \
     --from-file ../gengtype-gcc-04-filesrules/ > \
     $HOME/tmp/gengtype_patch_5_of_N__typedopt-relto04.diff

In am also attaching for convenience the cumulated patches against
trunk 163987 as a gzip file
gengtype_patch_5_of_N__typedopt-cumulatedto04-trunkrev-163987.diff.gz

######## gcc/ChangeLog entry relative to patch 4/N completed! [filesrules]
2010-09-11  Jeremie Salvucci  <jeremie.salvucci@free.fr>
	    Basile Starynkevitch  <basile@starynkevitch.net>

	* gengtype.c
	(enum typekind, struct options, struct nested_ptr_data)
	(struct pair, NUM_PARAM, enum gc_used_enum, struct type, UNION_P)
	(UNION_OR_STRUCT_P): Moved into gengtype.h

	(string_type, scalar_nonchar, scalar_char): Removed static and
	added state_number fake value.
	(typedefs, structures, param_structs, variables): Removed static.
	(create_option): Removed function.
	(create_string_option, create_type_option, created_nested_option):
	New.
	(created_nested_ptr_option, create_optional_field_)
	(adjust_field_rtx_def, adjust_field_tree_exp): Updated accordingly.
	(adjust_field_type, process_gc_options, output_mangled_typename)
	(walk_type, write_func_for_structure, write_types, write_roots)
	(note_def_vec, dump_options): Ditto.  Access to options is
	protected by tests on their kind.

	* gengtype.h: Added a lot of comments.  Moved many definitions
	from gengtype.h and updated them.
	(typedef, structures, param_structs, variables): Declared extern.
	(enum typekind): Moved from gengtype.c and added TYPE_NONE.
	(enum option_kind): New.
	(struct options): Added discriminating kind, and info union.
	(struct nested_ptr_data): Moved from gengtype.c.
	(create_string_option, create_type_option, create_nested_option):
	New.
	(struct pair, enum_gc_used_enum, NUM_PARAM): Moved
	from gengtype.c and commented more.
	(struct_type): Ditto, added state_number.
	(string_type, scalar_nonchar, scalar_char): Moved from gengtype.c.
	(type_lineloc): New function.
	(UNION_P, UNION_OR_STRUCT_P): Moved from gengtype.c and commented
	more.
	(struct outf): Indented better.

	* gengtype-parse.c (str_optvalue_opt, type_optvalue, option):
	Updated for our discriminated option.

################################################################

Comments and/or Ok for trunk are welcome!

Cheers.

Comments

Laurynas Biveinis Sept. 13, 2010, 6:57 a.m. UTC | #1
2010/9/11 Basile Starynkevitch <basile@starynkevitch.net>:

+options_p
+create_type_option (options_p next, const char* name, type_p info)

+options_p
+create_nested_option (options_p next, const char* name,
+		      struct nested_ptr_data* info)

You did not address my earlier remark about these two needing their
own comments.

+/* Discrimating kind of types we can understand.  */
+enum typekind {
+  TYPE_NONE=0,		/* Never used, so zero-ed memory is
+			   invalid. */
+  TYPE_SCALAR,		/* Scalar types like char. */
+  TYPE_STRING,		/* The string type. */
+  TYPE_STRUCT,		/* Type for GTY-ed struct-ures. */
+  TYPE_UNION,			/* Type for GTY-ed discriminated

Watch comment indentation.

+  OPTION_TYPE,			/* A type-valued option. */
+  OPTION_NESTED			/* Option data for 'nested_ptr'. */

Here too.

+struct options {
+  struct options *next;		/* next option of the same pair. */
+  const char *name;		/* GTY option name. */

And everywhere in struct options.

+    /* TYPE__NONE is impossible. */

TYPE_NONE

 /* Structure representing an output file.  */
-struct outf
-{
-    struct outf *next;
-    const char *name;
-    size_t buflength;
-    size_t bufused;
-    char *buf;
+struct outf {
+  struct outf *next;
+  const char *name;
+  size_t buflength;
+  size_t bufused;
+  char *buf;
 };

Please do not reformat the code you don't touch otherwise.
diff mbox

Patch

--- ../gengtype-gcc-04-filesrules//gengtype.c	2010-09-10 21:45:35.000000000 +0200
+++ gcc/gengtype.c	2010-09-11 15:18:06.000000000 +0200
@@ -31,99 +31,6 @@ 
 
 /* Data types, macros, etc. used only in this file.  */
 
-/* Kinds of types we can understand.  */
-enum typekind {
-  TYPE_SCALAR,
-  TYPE_STRING,
-  TYPE_STRUCT,
-  TYPE_UNION,
-  TYPE_POINTER,
-  TYPE_ARRAY,
-  TYPE_LANG_STRUCT,
-  TYPE_PARAM_STRUCT
-};
-
-
-/* A way to pass data through to the output end.  */
-struct options
-{
-  struct options *next;
-  const char *name;
-  const char *info;
-};
-
-/* Option data for the 'nested_ptr' option.  */
-struct nested_ptr_data
-{
-  type_p type;
-  const char *convert_to;
-  const char *convert_from;
-};
-
-/* A name and a type.  */
-struct pair
-{
-  pair_p next;
-  const char *name;
-  type_p type;
-  struct fileloc line;
-  options_p opt;
-};
-
-#define NUM_PARAM 10
-
-/* A description of a type.  */
-enum gc_used_enum
-  {
-    GC_UNUSED = 0,
-    GC_USED,
-    /* Used for structures whose definitions we haven't seen so far when
-       we encounter a pointer to it that is annotated with ``maybe_undef''.
-       If after reading in everything we don't have source file
-       information for it, we assume that it never has been defined. */
-    GC_MAYBE_POINTED_TO,
-    GC_POINTED_TO
-  };
-
-struct type
-{
-  enum typekind kind;
-  type_p next;
-  type_p pointer_to;
-  enum gc_used_enum gc_used;
-  union {
-    type_p p;
-    struct {
-      const char *tag;
-      struct fileloc line;
-      pair_p fields;
-      options_p opt;
-      lang_bitmap bitmap;
-      type_p lang_struct;
-    } s;
-    bool scalar_is_char;
-    struct {
-      type_p p;
-      const char *len;
-    } a;
-    struct {
-      type_p stru;
-      type_p param[NUM_PARAM];
-      struct fileloc line;
-    } param_struct;
-  } u;
-};
-
-#define UNION_P(x)					\
- ((x)->kind == TYPE_UNION || 				\
-  ((x)->kind == TYPE_LANG_STRUCT 			\
-   && (x)->u.s.lang_struct->kind == TYPE_UNION))
-#define UNION_OR_STRUCT_P(x)			\
- ((x)->kind == TYPE_UNION 			\
-  || (x)->kind == TYPE_STRUCT 			\
-  || (x)->kind == TYPE_LANG_STRUCT)
-
-
 
 
 
@@ -550,26 +457,27 @@  read_input_list (const char *listname)
 
 /* The one and only TYPE_STRING.  */
 
-static struct type string_type = {
-  TYPE_STRING, 0, 0, GC_USED, {0}
+struct type string_type = {
+  TYPE_STRING, 0, 0, 0, GC_USED, {0}
 };
 
 /* The two and only TYPE_SCALARs.  Their u.scalar_is_char flags are
    set to appropriate values at the beginning of main.  */
 
-static struct type scalar_nonchar = {
-  TYPE_SCALAR, 0, 0, GC_USED, {0}
+struct type scalar_nonchar = {
+  TYPE_SCALAR, 0, 0, 0, GC_USED, {0}
 };
-static struct type scalar_char = {
-  TYPE_SCALAR, 0, 0, GC_USED, {0}
+
+struct type scalar_char = {
+  TYPE_SCALAR, 0, 0, 0, GC_USED, {0}
 };
 
 /* Lists of various things.  */
 
-static pair_p typedefs;
-static type_p structures;
-static type_p param_structs;
-static pair_p variables;
+pair_p typedefs;
+type_p structures;
+type_p param_structs;
+pair_p variables;
 
 static type_p find_param_structure
   (type_p t, type_p param[NUM_PARAM]);
@@ -811,19 +719,48 @@  create_array (type_p t, const char *len)
   return v;
 }
 
-/* Return an options structure with name NAME and info INFO.  NEXT is the
-   next option in the chain.  */
 
+/* Create various options structures with name NAME and info INFO.
+   NEXT is the next option in the chain.  */
 options_p
-create_option (options_p next, const char *name, const void *info)
+create_string_option (options_p next, const char* name, const char* info)
 {
-  options_p o = XNEW (struct options);
+  options_p o;
+  o = XCNEW (struct options);
   o->next = next;
   o->name = name;
-  o->info = (const char*) info;
+  o->kind = OPTION_STRING;
+  o->info.string = info;
   return o;
 }
 
+
+options_p
+create_type_option (options_p next, const char* name, type_p info)
+{
+  options_p o;
+  o = XCNEW (struct options);
+  o->next = next;
+  o->name = name;
+  o->kind = OPTION_TYPE;
+  o->info.type = info;
+  return o;
+}
+
+options_p
+create_nested_option (options_p next, const char* name, 
+		      struct nested_ptr_data* info)
+{
+  options_p o;
+  o = XCNEW (struct options);
+  o->next = next;
+  o->name = name;
+  o->kind = OPTION_NESTED;
+  o->info.nested = info;
+  return o;
+}
+
+
 /* Return an options structure for a "nested_ptr" option.  */
 options_p
 create_nested_ptr_option (options_p next, type_p t,
@@ -834,7 +771,7 @@  create_nested_ptr_option (options_p next
   d->type = adjust_field_type (t, 0);
   d->convert_to = to;
   d->convert_from = from;
-  return create_option (next, "nested_ptr", d);
+  return create_nested_option (next, "nested_ptr", d);
 }
 
 /* Add a variable named S of type T with options O defined at POS,
@@ -901,15 +838,15 @@  create_optional_field_ (pair_p next, typ
      The field has a tag of "1".  This allows us to make the presence
      of a field of type TYPE depend on some boolean "desc" being true.  */
   union_fields = create_field (NULL, type, "");
-  union_fields->opt = create_option (union_fields->opt, "dot", "");
-  union_fields->opt = create_option (union_fields->opt, "tag", "1");
+  union_fields->opt = create_string_option (union_fields->opt, "dot", "");
+  union_fields->opt = create_string_option (union_fields->opt, "tag", "1");
   union_type = new_structure (xasprintf ("%s_%d", "fake_union", id++), 1,
 			      &lexer_line, union_fields, NULL);
 
   /* Create the field and give it the new fake union type.  Add a "desc"
      tag that specifies the condition under which the field is valid.  */
   return create_field_all (next, union_type, name,
-			   create_option (0, "desc", cond),
+			   create_string_option (0, "desc", cond),
 			   this_file, line);
 }
 #define create_optional_field(next,type,name,cond)	\
@@ -1041,7 +978,7 @@  adjust_field_rtx_def (type_p t, options_
       return &string_type;
     }
 
-  nodot = create_option (NULL, "dot", "");
+  nodot = create_string_option (NULL, "dot", "");
 
   rtx_tp = create_pointer (find_structure ("rtx_def", 0));
   rtvec_tp = create_pointer (find_structure ("rtvec_def", 0));
@@ -1081,9 +1018,9 @@  adjust_field_rtx_def (type_p t, options_
 	/* NOTE_INSN_MAX is used as the default field for line
 	   number notes.  */
 	if (c == NOTE_INSN_MAX)
-	  note_flds->opt = create_option (nodot, "default", "");
+	  note_flds->opt = create_string_option (nodot, "default", "");
 	else
-	  note_flds->opt = create_option (nodot, "tag", note_insn_name[c]);
+	  note_flds->opt = create_string_option (nodot, "tag", note_insn_name[c]);
       }
     note_union_tp = new_structure ("rtx_def_note_subunion", 1,
 				   &lexer_line, note_flds, NULL);
@@ -1093,10 +1030,10 @@  adjust_field_rtx_def (type_p t, options_
     pair_p sym_flds;
 
     sym_flds = create_field (NULL, tree_tp, "rt_tree");
-    sym_flds->opt = create_option (nodot, "default", "");
+    sym_flds->opt = create_string_option (nodot, "default", "");
 
     sym_flds = create_field (sym_flds, constant_tp, "rt_constant");
-    sym_flds->opt = create_option (nodot, "tag", "1");
+    sym_flds->opt = create_string_option (nodot, "tag", "1");
 
     symbol_union_tp = new_structure ("rtx_def_symbol_subunion", 1,
 				     &lexer_line, sym_flds, NULL);
@@ -1215,10 +1152,10 @@  adjust_field_rtx_def (type_p t, options_
 					       subname));
 	  subfields->opt = nodot;
 	  if (t == note_union_tp)
-	    subfields->opt = create_option (subfields->opt, "desc",
+	    subfields->opt = create_string_option (subfields->opt, "desc",
 					    "NOTE_KIND (&%0)");
 	  if (t == symbol_union_tp)
-	    subfields->opt = create_option (subfields->opt, "desc",
+	    subfields->opt = create_string_option (subfields->opt, "desc",
 					    "CONSTANT_POOL_ADDRESS_P (&%0)");
 	}
 
@@ -1239,7 +1176,7 @@  adjust_field_rtx_def (type_p t, options_
 	ftag[nmindex] = TOUPPER (ftag[nmindex]);
 
       flds = create_field (flds, substruct, "");
-      flds->opt = create_option (nodot, "tag", ftag);
+      flds->opt = create_string_option (nodot, "tag", ftag);
     }
 
   return new_structure ("rtx_def_subunion", 1, &lexer_line, flds, nodot);
@@ -1264,12 +1201,12 @@  adjust_field_tree_exp (type_p t, options
       return &string_type;
     }
 
-  nodot = create_option (NULL, "dot", "");
+  nodot = create_string_option (NULL, "dot", "");
 
   flds = create_field (NULL, t, "");
-  flds->opt = create_option (nodot, "length",
+  flds->opt = create_string_option (nodot, "length",
 			     "TREE_OPERAND_LENGTH ((tree) &%0)");
-  flds->opt = create_option (flds->opt, "default", "");
+  flds->opt = create_string_option (flds->opt, "default", "");
 
   return new_structure ("tree_exp_subunion", 1, &lexer_line, flds, nodot);
 }
@@ -1299,10 +1236,11 @@  adjust_field_type (type_p t, options_p o
   for (; opt; opt = opt->next)
     if (strcmp (opt->name, "length") == 0)
       length_p = 1;
-    else if (strcmp (opt->name, "param_is") == 0
+    else if ((strcmp (opt->name, "param_is") == 0
 	     || (strncmp (opt->name, "param", 5) == 0
 		 && ISDIGIT (opt->name[5])
 		 && strcmp (opt->name + 6, "_is") == 0))
+	     && opt->kind == OPTION_TYPE)
       {
 	int num = ISDIGIT (opt->name[5]) ? opt->name[5] - '0' : 0;
 
@@ -1319,13 +1257,14 @@  adjust_field_type (type_p t, options_p o
 	if (params[num] != NULL)
 	  error_at_line (&lexer_line, "duplicate `%s' option", opt->name);
 	if (! ISDIGIT (opt->name[5]))
-	  params[num] = create_pointer (CONST_CAST2(type_p, const char *, opt->info));
+	  params[num] = create_pointer (opt->info.type);
 	else
-	  params[num] = CONST_CAST2 (type_p, const char *, opt->info);
+	  params[num] = opt->info.type;
       }
-    else if (strcmp (opt->name, "special") == 0)
+    else if (strcmp (opt->name, "special") == 0
+	     && opt->kind == OPTION_STRING)
       {
-	const char *special_name = opt->info;
+	const char *special_name = opt->info.string;
 	if (strcmp (special_name, "tree_exp") == 0)
 	  t = adjust_field_tree_exp (t, opt);
 	else if (strcmp (special_name, "rtx_def") == 0)
@@ -1369,8 +1308,9 @@  process_gc_options (options_p opt, enum
 {
   options_p o;
   for (o = opt; o; o = o->next)
-    if (strcmp (o->name, "ptr_alias") == 0 && level == GC_POINTED_TO)
-      set_gc_used_type (CONST_CAST2 (type_p, const char *, o->info),
+    if (strcmp (o->name, "ptr_alias") == 0 && level == GC_POINTED_TO
+	&& o->kind == OPTION_TYPE)
+      set_gc_used_type (o->info.type,
 			GC_POINTED_TO, NULL);
     else if (strcmp (o->name, "maybe_undef") == 0)
       *maybe_undef = 1;
@@ -1380,8 +1320,9 @@  process_gc_options (options_p opt, enum
       *length = 1;
     else if (strcmp (o->name, "skip") == 0)
       *skip = 1;
-    else if (strcmp (o->name, "nested_ptr") == 0)
-      *nested_ptr = ((const struct nested_ptr_data *) o->info)->type;
+    else if (strcmp (o->name, "nested_ptr") == 0
+	     && o->kind == OPTION_NESTED)
+      *nested_ptr = ((const struct nested_ptr_data *) o->info.nested)->type;
 }
 
 /* Set the gc_used field of T to LEVEL, and handle the types it references.  */
@@ -2316,6 +2257,8 @@  output_mangled_typename (outf_p of, cons
     oprintf (of, "Z");
   else switch (t->kind)
     {
+    case TYPE_NONE:
+      fatal ("uninitialized type to mangle");
     case TYPE_POINTER:
       oprintf (of, "P");
       output_mangled_typename (of, t->u.p);
@@ -2409,8 +2352,8 @@  walk_type (type_p t, struct walk_type_da
 
   d->needs_cast_p = false;
   for (oo = d->opt; oo; oo = oo->next)
-    if (strcmp (oo->name, "length") == 0)
-      length = oo->info;
+    if (strcmp (oo->name, "length") == 0 && oo->kind == OPTION_STRING)
+      length = oo->info.string;
     else if (strcmp (oo->name, "maybe_undef") == 0)
       maybe_undef_p = 1;
     else if (strncmp (oo->name, "use_param", 9) == 0
@@ -2418,12 +2361,12 @@  walk_type (type_p t, struct walk_type_da
       use_param_num = oo->name[9] == '\0' ? 0 : oo->name[9] - '0';
     else if (strcmp (oo->name, "use_params") == 0)
       use_params_p = 1;
-    else if (strcmp (oo->name, "desc") == 0)
-      desc = oo->info;
+    else if (strcmp (oo->name, "desc") == 0 && oo->kind == OPTION_STRING)
+      desc = oo->info.string;
     else if (strcmp (oo->name, "mark_hook") == 0)
       ;
-    else if (strcmp (oo->name, "nested_ptr") == 0)
-      nested_ptr_d = (const struct nested_ptr_data *) oo->info;
+    else if (strcmp (oo->name, "nested_ptr") == 0 && oo->kind == OPTION_NESTED)
+      nested_ptr_d = (const struct nested_ptr_data *) oo->info.nested;
     else if (strcmp (oo->name, "dot") == 0)
       ;
     else if (strcmp (oo->name, "tag") == 0)
@@ -2678,8 +2621,9 @@  walk_type (type_p t, struct walk_type_da
 
 	/* Some things may also be defined in the structure's options.  */
 	for (o = t->u.s.opt; o; o = o->next)
-	  if (! desc && strcmp (o->name, "desc") == 0)
-	    desc = o->info;
+	  if (! desc && strcmp (o->name, "desc") == 0 
+	      && o->kind == OPTION_STRING)
+	    desc = o->info.string;
 
 	d->prev_val[2] = oldval;
 	d->prev_val[1] = oldprevval2;
@@ -2709,16 +2653,19 @@  walk_type (type_p t, struct walk_type_da
 
 	    d->reorder_fn = NULL;
 	    for (oo = f->opt; oo; oo = oo->next)
-	      if (strcmp (oo->name, "dot") == 0)
-		dot = oo->info;
-	      else if (strcmp (oo->name, "tag") == 0)
-		tagid = oo->info;
+	      if (strcmp (oo->name, "dot") == 0
+		  && oo->kind == OPTION_STRING)
+		dot = oo->info.string;
+	      else if (strcmp (oo->name, "tag") == 0
+		       && oo->kind == OPTION_STRING)
+		tagid = oo->info.string;
 	      else if (strcmp (oo->name, "skip") == 0)
 		skip_p = 1;
 	      else if (strcmp (oo->name, "default") == 0)
 		default_p = 1;
-	      else if (strcmp (oo->name, "reorder") == 0)
-		d->reorder_fn = oo->info;
+	      else if (strcmp (oo->name, "reorder") == 0
+		       && oo->kind == OPTION_STRING)
+		d->reorder_fn = oo->info.string;
 	      else if (strncmp (oo->name, "use_param", 9) == 0
 		       && (oo->name[9] == '\0' || ISDIGIT (oo->name[9])))
 		use_param_p = 1;
@@ -2960,14 +2907,18 @@  write_func_for_structure (type_p orig_s,
   d.of = get_output_file_for_structure (s, param);
 
   for (opt = s->u.s.opt; opt; opt = opt->next)
-    if (strcmp (opt->name, "chain_next") == 0)
-      chain_next = opt->info;
-    else if (strcmp (opt->name, "chain_prev") == 0)
-      chain_prev = opt->info;
-    else if (strcmp (opt->name, "chain_circular") == 0)
-      chain_circular = opt->info;
-    else if (strcmp (opt->name, "mark_hook") == 0)
-      mark_hook_name = opt->info;
+    if (strcmp (opt->name, "chain_next") == 0
+	&& opt->kind == OPTION_STRING)
+      chain_next = opt->info.string;
+    else if (strcmp (opt->name, "chain_prev") == 0
+	&& opt->kind == OPTION_STRING)
+      chain_prev = opt->info.string;
+    else if (strcmp (opt->name, "chain_circular") == 0
+	&& opt->kind == OPTION_STRING)
+      chain_circular = opt->info.string;
+    else if (strcmp (opt->name, "mark_hook") == 0
+	&& opt->kind == OPTION_STRING)
+      mark_hook_name = opt->info.string;
 
   if (chain_prev != NULL && chain_next == NULL)
     error_at_line (&s->u.s.line, "chain_prev without chain_next");
@@ -3139,9 +3090,10 @@  write_types (outf_p output_header, type_
 		 "  } while (0)\n");
 
 	for (opt = s->u.s.opt; opt; opt = opt->next)
-	  if (strcmp (opt->name, "ptr_alias") == 0)
+	  if (strcmp (opt->name, "ptr_alias") == 0
+	      && opt->kind == OPTION_TYPE)
 	    {
-	      const_type_p const t = (const_type_p) opt->info;
+	      const_type_p const t = (const_type_p) opt->info.type;
 	      if (t->kind == TYPE_STRUCT
 		  || t->kind == TYPE_UNION
 		  || t->kind == TYPE_LANG_STRUCT)
@@ -3366,9 +3318,10 @@  write_local (outf_p output_header, type_
 	  continue;
 
 	for (opt = s->u.s.opt; opt; opt = opt->next)
-	  if (strcmp (opt->name, "ptr_alias") == 0)
+	  if (strcmp (opt->name, "ptr_alias") == 0
+	      && opt->kind == OPTION_TYPE)
 	    {
-	      const_type_p const t = (const_type_p) opt->info;
+	      const_type_p const t = (const_type_p) opt->info.type;
 	      if (t->kind == TYPE_STRUCT
 		  || t->kind == TYPE_UNION
 		  || t->kind == TYPE_LANG_STRUCT)
@@ -3696,8 +3649,9 @@  write_root (outf_p f, pair_p v, type_p t
 	    for (o = fld->opt; o; o = o->next)
 	      if (strcmp (o->name, "skip") == 0)
 		skip_p = 1;
-	      else if (strcmp (o->name, "desc") == 0)
-		desc = o->info;
+	      else if (strcmp (o->name, "desc") == 0
+		       && o->kind == OPTION_STRING)
+		desc = o->info.string;
 	      else if (strcmp (o->name, "param_is") == 0)
 		;
 	      else
@@ -3718,8 +3672,9 @@  write_root (outf_p f, pair_p v, type_p t
 		    options_p oo;
 
 		    for (oo = ufld->opt; oo; oo = oo->next)
-		      if (strcmp (oo->name, "tag") == 0)
-			tag = oo->info;
+		      if (strcmp (oo->name, "tag") == 0
+		       && oo->kind == OPTION_STRING)
+			tag = oo->info.string;
 		    if (tag == NULL || strcmp (tag, desc) != 0)
 		      continue;
 		    if (validf != NULL)
@@ -3895,8 +3850,9 @@  write_roots (pair_p variables, bool emit
       options_p o;
 
       for (o = v->opt; o; o = o->next)
-	if (strcmp (o->name, "length") == 0)
-	  length = o->info;
+	if (strcmp (o->name, "length") == 0
+		       && o->kind == OPTION_STRING)
+	  length = o->info.string;
 	else if (strcmp (o->name, "deletable") == 0)
 	  deletable_p = 1;
 	else if (strcmp (o->name, "param_is") == 0)
@@ -4021,8 +3977,9 @@  write_roots (pair_p variables, bool emit
       for (o = v->opt; o; o = o->next)
 	if (strcmp (o->name, "length") == 0)
 	  length_p = 1;
-	else if (strcmp (o->name, "if_marked") == 0)
-	  if_marked = o->info;
+	else if (strcmp (o->name, "if_marked") == 0
+		       && o->kind == OPTION_STRING)
+	  if_marked = o->info.string;
 
       if (if_marked == NULL)
 	continue;
@@ -4158,7 +4115,7 @@  note_def_vec (const char *type_name, boo
   else
     {
       t = resolve_typedef (type_name, pos);
-      o = create_option (0, "length", "%h.num");
+      o = create_string_option (0, "length", "%h.num");
     }
 
   /* We assemble the field list in reverse order.  */
@@ -4449,8 +4406,22 @@  dump_options (int indent, options_p opt)
   o = opt;
   while (o)
     {
-       printf ("%s:%s ", o->name, o->info);
-       o = o->next;
+      switch (o->kind) 
+	{
+	case OPTION_STRING:
+	  printf ("%s:string %s ", o->name, o->info.string);
+	  break;
+	case OPTION_TYPE:
+	  printf ("%s:type ", o->name);
+	  dump_type (indent+1, o->info.type);
+	  break;
+	case OPTION_NESTED:
+	  printf ("%s:nested ", o->name);
+	  break;
+	case OPTION_NONE:
+	  fatal ("corrupted option %p: %s", (void*) o, o->name);
+	}
+      o = o->next;
     }
   printf ("\n");
 }
--- ../gengtype-gcc-04-filesrules//gengtype.h	2010-09-10 21:46:34.000000000 +0200
+++ gcc/gengtype.h	2010-09-11 14:46:53.000000000 +0200
@@ -133,26 +133,261 @@  struct fileloc {
 extern const char **lang_dir_names;
 extern size_t num_lang_dirs;
 
-
-
-/* Data types handed around within, but opaque to, the lexer and parser.  */
+/* Common types, for structures defined below.  */
 typedef struct pair *pair_p;
 typedef struct type *type_p;
 typedef const struct type *const_type_p;
 typedef struct options *options_p;
 
+/* Various things, organized as linked lists, needed both in
+   gengtype.c & in gengtype-state.c */
+extern pair_p typedefs;
+extern type_p structures;
+extern type_p param_structs;
+extern pair_p variables;
+
+
+
+/* Discrimating kind of types we can understand.  */
+enum typekind {
+  TYPE_NONE=0,		/* Never used, so zero-ed memory is
+			   invalid. */
+  TYPE_SCALAR,		/* Scalar types like char. */
+  TYPE_STRING,		/* The string type. */
+  TYPE_STRUCT,		/* Type for GTY-ed struct-ures. */
+  TYPE_UNION,			/* Type for GTY-ed discriminated
+				   union-s. */
+  TYPE_POINTER,		/* Pointer type to GTY-ed type. */
+  TYPE_ARRAY,		/* Array of GTY-ed types. */
+  TYPE_LANG_STRUCT,	/* GCC front-end language specific
+			   struct-s. Various languages may have
+			   homonymous but different
+			   struct-s. */
+  TYPE_PARAM_STRUCT	/* Type for parametrized struct-ures,
+			   e.g. hash_t hash-tables, ...  See
+			   (param_is, use_param, param1_is, param2_is,
+			   ... use_param1, use_param_2,
+			   ... use_params) GTY options.  */
+};
+
+/* Discriminating kind for options. */
+enum option_kind {
+  OPTION_NONE=0,		/* Never used, so zero-ed memory is
+				   invalid. */
+  OPTION_STRING,		/* A string-valued option. Most options
+				   are strings. */
+  OPTION_TYPE,			/* A type-valued option. */
+  OPTION_NESTED			/* Option data for 'nested_ptr'. */
+};
+
+
+/* A way to pass data through to the output end.  */
+struct options {
+  struct options *next;		/* next option of the same pair. */
+  const char *name;		/* GTY option name. */
+  enum option_kind kind;		/* disciminating option kind. */
+  /* the union below is discriminated by the 'kind' field above. */
+  union {
+    const char* string;		    /* when OPTION_STRING. */
+    type_p type;		    /* when OPTION_TYPE. */
+    struct nested_ptr_data* nested; /* when OPTION_NESTED. */
+  } info;
+};
+
+
+/* Option data for the 'nested_ptr' option.  */
+struct nested_ptr_data {
+  type_p type;
+  const char *convert_to;
+  const char *convert_from;
+};
+
+/* Some functions to create various options structures with name NAME
+   and info INFO.  NEXT is the next option in the chain.  */
+
+/* Create a string option. */
+options_p create_string_option (options_p next, const char* name, const char* info);
+
+/* Create a type option. */
+options_p create_type_option (options_p next, const char* name, type_p info);
+
+/* Create a nested option. */
+options_p create_nested_option (options_p next, const char* name, 
+				struct nested_ptr_data* info);
+
+/* Create a nested pointer option. */
+options_p create_nested_ptr_option (options_p, type_p t,
+				    const char *from, const char *to);
+
+/* A name and a type.  */
+struct pair {
+  pair_p next;			/* the next pair in the linked list. */
+  const char *name;		/* the defined name. */
+  type_p type;			/* its GTY-ed type. */
+  struct fileloc line;		/* the file location. */
+  options_p opt;		/* GTY options, as a linked list. */
+};
+
+/* Usage information for GTY-ed types.  Gengtype has to care only of
+   used GTY-ed types.  Types are initially unused, and their usage is
+   computed by set_gc_used_type and set_gc_used functions. */
+
+enum gc_used_enum {
+
+  /* We need that zero-ed types are initially unused. */
+  GC_UNUSED=0,	
+		
+  /* The GTY-ed type is used, e.g by a GTY-ed variable or a field
+     inside a GTY-ed used type.  */
+  GC_USED,			
+
+  /* For GTY-ed structures whose definitions we haven't seen so far
+     when we encounter a pointer to it that is annotated with
+     ``maybe_undef''.  If after reading in everything we don't have
+     source file information for it, we assume that it never has been
+     defined. */
+  GC_MAYBE_POINTED_TO,	        
+
+  /* For known GTY-ed structures which are pointed to by GTY-ed
+     variables or fields.  */
+  GC_POINTED_TO
+};
+
+/* We have at most ten type parameters in parameterized structures.  */
+#define NUM_PARAM 10
+
+/* Our type structure describes all types handled by gengtype. */
+struct type {
+  /* Discriminating kind, cannot be TYPE_NONE. */
+  enum typekind kind;  
+
+  /* For top-level struct-s or union-s, the 'next' field link the
+     global list 'structures' or 'param_structs'; for lang_struct-s,
+     their homonymous struct-s are linked using this next field. The
+     homonymous list starts at the s.lang_struct field of the
+     lang_struct. See the new_structure function for details.  This is
+     tricky!  */
+  type_p next;			
+
+  /* State number used when writing & reading the persistent state.  A
+     type with a positive number has already been written.  For ease
+     of debugging, newly allocated types have a unique negative
+     number. */
+  int state_number;
+
+  /* Each GTY-ed type which is pointed to by some GTY-ed type knows
+     the GTY pointer type pointing to it.  See create_pointer
+     function. */
+  type_p pointer_to;
+
+  /* Type usage information, computed by set_gc_used_type and
+     set_gc_used functions. */
+  enum gc_used_enum gc_used;
+
+  /* The following union is discriminated by the 'kind' field above. */
+  union {
+    /* TYPE__NONE is impossible. */
+
+    /* when TYPE_POINTER:  */
+    type_p p;
+
+    /* when TYPE_STRUCT or TYPE_UNION or TYPE_LANG_STRUCT, we have an
+       aggregate type containing fields: */		
+    struct {	
+      const char *tag;		/* the aggragate tag, if any. */
+      struct fileloc line;	/* the source location. */
+      pair_p fields;		/* the linked list of fields. */
+      options_p opt;		/* the GTY options if any. */
+      lang_bitmap bitmap;	/* the set of front-end languages
+				   using that GTY-ed aggregate.  */
+      /* For TYPE_LANG_STRUCT, the lang_struct field gives the first
+	 element of a linked list of homonymous struct or union types.
+	 Within this list, each homonymous type has as its lang_struct
+	 field the original TYPE_LANG_STRUCT type.  This is a dirty
+	 trick, see the new_structure function for details.  */
+      type_p lang_struct;
+    } s;
+
+    /* when TYPE_SCALAR: */
+    bool scalar_is_char;
+
+    /* when TYPE_ARRAY: */
+    struct {
+      type_p p;			/* the array component type. */
+      const char *len;		/* the string if any giving its length. */
+    } a;
+
+    /* when TYPE_PARAM_STRUCT for (param_is, use_param, param1_is,
+       param2_is, ... use_param1, use_param_2, ... use_params) GTY
+       options. */
+    struct {
+      type_p stru;		/* the generic GTY-ed type. */
+      type_p param[NUM_PARAM];	/* the actual parameter types. */
+      struct fileloc line;	/* the source location. */
+    } param_struct;
+
+  } u;
+};
+
+/* The one and only TYPE_STRING.  */
+extern struct type string_type;
+
+/* The two and only TYPE_SCALARs.  Their u.scalar_is_char flags are
+   set appropriately early in main.  */
+extern struct type scalar_nonchar;
+extern struct type scalar_char;
+
+/* Gives the file location of a type, if any.  */
+static inline struct fileloc*
+type_lineloc (const_type_p ty)
+{
+  if (!ty) 
+    return NULL;
+  switch (ty->kind) {
+  case TYPE_NONE: 
+    fatal ("type_lineloc on bad zeroed type %p", (const void*)ty);
+  case TYPE_STRUCT:
+  case TYPE_UNION:
+  case TYPE_LANG_STRUCT:
+    return CONST_CAST (struct fileloc*, &ty->u.s.line);
+  case TYPE_PARAM_STRUCT:
+    return CONST_CAST (struct fileloc*, &ty->u.param_struct.line);
+  case TYPE_SCALAR:
+  case TYPE_STRING:
+  case TYPE_POINTER:
+  case TYPE_ARRAY:
+    return NULL;
+  }
+  fatal ("type_lineloc on corrupted type %p kd#%d", 
+	 (const void*)ty, (int) ty->kind);
+}
+
+/* Test if a type is a union, either a plain one or a language
+   specific one.  */
+#define UNION_P(x)					\
+    ((x)->kind == TYPE_UNION ||				\
+     ((x)->kind == TYPE_LANG_STRUCT 			\
+      && (x)->u.s.lang_struct->kind == TYPE_UNION))
+
+/* Test if a type is a union or a structure, perhaps a language
+   specific one.  */
+#define UNION_OR_STRUCT_P(x)			\
+    ((x)->kind == TYPE_UNION 			\
+     || (x)->kind == TYPE_STRUCT		\
+     || (x)->kind == TYPE_LANG_STRUCT)
+
+
 /* Variables used to communicate between the lexer and the parser.  */
 extern int lexer_toplevel_done;
 extern struct fileloc lexer_line;
 
 /* Structure representing an output file.  */
-struct outf
-{
-    struct outf *next;
-    const char *name;
-    size_t buflength;
-    size_t bufused;
-    char *buf;
+struct outf {
+  struct outf *next;
+  const char *name;
+  size_t buflength;
+  size_t bufused;
+  char *buf;
 };
 typedef struct outf* outf_p;
 
--- ../gengtype-gcc-04-filesrules//gengtype-parse.c	2010-09-10 21:46:34.000000000 +0200
+++ gcc/gengtype-parse.c	2010-09-11 15:15:14.000000000 +0200
@@ -343,7 +343,7 @@  str_optvalue_opt (options_p prev)
       value = string_seq ();
       require (')');
     }
-  return create_option (prev, name, value);
+  return create_string_option (prev, name, value);
 }
 
 /* absdecl: type '*'*
@@ -381,7 +381,7 @@  type_optvalue (options_p prev, const cha
   require ('(');
   ty = absdecl ();
   require (')');
-  return create_option (prev, name, ty);
+  return create_type_option (prev, name, ty);
 }
 
 /* Nested pointer data: '(' type '*'* ',' string_seq ',' string_seq ')' */
@@ -431,7 +431,7 @@  option (options_p prev)
       parse_error ("expected an option keyword, have %s",
 		   print_cur_token ());
       advance ();
-      return create_option (prev, "", "");
+      return create_string_option (prev, "", "");
     }
 }