--- ../gengtype-gcc-02-verbosity/gengtype.c	2010-09-08 16:36:26.000000000 +0200
+++ gcc/gengtype.c	2010-09-09 16:05:41.000000000 +0200
@@ -123,7 +123,6 @@ struct type
 
 
 
-const char *get_output_file_name (const char *);
 
 
 /* The list of output files.  */
@@ -137,12 +136,12 @@ outf_p header_file;
 /* The name of the file containing the list of input files. */
 static char* inputlist;
 
-/* The plugin input files and their number; in that case only
-   a single file is produced.  */
-static char** plugin_files;
+/* The plugin input files and their number; in plugin mode only a
+   single file is produced.  */
+static input_file** plugin_files;
 static size_t nb_plugin_files;
 
-/* the generated plugin output file and name.  */
+/* the generated plugin output file and name in plugin mode.  */
 static outf_p plugin_output;
 static char* plugin_output_filename;
 
@@ -164,12 +163,11 @@ int verbosity_level;
 
 static outf_p create_file (const char *, const char *);
 
-static const char * get_file_basename (const char *);
-static const char * get_file_realbasename (const char *);
-static const char * get_file_srcdir_relative_path (const char *);
+static const char * get_file_basename (const input_file *);
+static const char * get_file_realbasename (const input_file *);
 
 static int get_prefix_langdir_index (const char *);
-static const char * get_file_langdir (const char *);
+static const char * get_file_langdir (const input_file *);
 
 
 /* Nonzero iff an error has occurred.  */
@@ -189,7 +187,8 @@ error_at_line (const struct fileloc *pos
 
   va_start (ap, msg);
 
-  fprintf (stderr, "%s:%d: ", pos->file, pos->line);
+  gcc_assert (pos != NULL && pos->file != NULL);
+  fprintf (stderr, "%s:%d: ", get_input_file_name (pos->file), pos->line);
   vfprintf (stderr, msg, ap);
   fputc ('\n', stderr);
   hit_error = true;
@@ -217,18 +216,17 @@ xasprintf (const char *format, ...)
 /* Input file handling. */
 
 /* Table of all input files.  */
-static const char **gt_files;
-static size_t num_gt_files;
+input_file** gt_files;
+size_t num_gt_files;
+
+/* Special files, initialized very early in main.  */
+input_file* this_file; 		/* for gengtype.c */
+input_file* system_h_file;	/* for system.h */
 
-/* A number of places use the name of this file for a location for
-   things that we can't rely on the source to define.  Make sure we
-   can still use pointer comparison on filenames.  */
-const char this_file[] = __FILE__;
-const char system_h_file[] = "system.h";
 
 /* Vector of per-language directories.  */
-static const char **lang_dir_names;
-static size_t num_lang_dirs;
+const char **lang_dir_names;
+size_t num_lang_dirs;
 
 /* An array of output files suitable for definitions.  There is one
    BASE_FILES entry for each language.  */
@@ -246,37 +244,6 @@ static outf_p *base_files;
    buffer set up by read_input_list.  It may be unaligned, so we have to
    read it byte-by-byte.  */
 
-static lang_bitmap
-get_lang_bitmap (const char *gtfile)
-{
-
-  if (gtfile == this_file || gtfile == system_h_file)
-    /* Things defined in this file are universal.  */
-    return (((lang_bitmap)1) << num_lang_dirs) - 1;
-  else
-    {
-      lang_bitmap n = 0;
-      int i;
-      for (i = -(int) sizeof (lang_bitmap); i < 0; i++)
-	n = (n << CHAR_BIT) + (unsigned char)gtfile[i];
-      return n;
-    }
-}
-
-/* Set the bitmap returned by get_lang_bitmap.  The only legitimate
-   caller of this function is read_input_list.  */
-static void
-set_lang_bitmap (char *gtfile, lang_bitmap n)
-{
-  int i;
-  for (i = -1; i >= -(int) sizeof (lang_bitmap); i--)
-    {
-      gtfile[i] = n & ((1U << CHAR_BIT)-1);
-      n >>= CHAR_BIT;
-    }
-}
-
-
 #if ENABLE_CHECKING
 /* Utility debugging function, printing the various type counts within
    a list of types.  Called thru the DBGPRINT_COUNT_TYPE macro.  */
@@ -468,11 +435,11 @@ read_input_list (const char *listname)
       size_t nfiles = 0;
       lang_bitmap curlangs = (1 << num_lang_dirs) - 1;
 
-      epos.file = listname;
+      epos.file = input_file_by_name (listname);
       epos.line = 0;
 
       lang_dir_names = XNEWVEC (const char *, num_lang_dirs);
-      gt_files = XNEWVEC (const char *, num_gt_files);
+      gt_files = XNEWVEC (input_file *, num_gt_files);
 
       for (;;)
 	{
@@ -502,13 +469,16 @@ read_input_list (const char *listname)
 	  else
 	    {
 	      size_t i;
+	      input_file *inpf = input_file_by_name (line);
 	      gcc_assert (nfiles <= num_gt_files);
 	      for (i = 0; i < nfiles; i++)
-		if (strcmp (gt_files[i], line) == 0)
+		/* Since the input_file-s are uniquely hash-consed, we
+		   can just compare pointers! */
+		if (gt_files[i] == inpf)
 		  {
 		    /* Throw away the string we just read, and add the
 		       current language to the existing string's bitmap.  */
-		    lang_bitmap bmap = get_lang_bitmap (gt_files[i]);
+		    lang_bitmap bmap = get_lang_bitmap (inpf);
 		    if (bmap & curlangs)
 		      error_at_line (&epos, "file %s specified more than once "
 				     "for language %s", line, langno == 0
@@ -516,13 +486,13 @@ read_input_list (const char *listname)
 				     : lang_dir_names[langno - 1]);
 
 		    bmap |= curlangs;
-		    set_lang_bitmap (CONST_CAST(char *, gt_files[i]), bmap);
+		    set_lang_bitmap (inpf, bmap);
 		    here = committed;
 		    goto next_line;
 		  }
 
-	      set_lang_bitmap (line, curlangs);
-	      gt_files[nfiles++] = line;
+	      set_lang_bitmap (inpf, curlangs);
+	      gt_files[nfiles++] = inpf;
 	    }
 	}
       /* Update the global counts now that we know accurately how many
@@ -745,16 +715,7 @@ new_structure (const char *name, int isu
      write out its mark routine.  */
   if (!strcmp (name, "location_s") && !isunion
       && pos->file == this_file)
-    {
-      size_t n;
-      for (n = 0; n < num_gt_files; n++)
-	if (!strcmp (gt_files[n] + strlen (gt_files[n]) - strlen ("input.h"),
-		     "input.h"))
-	  {
-	    s->u.s.line.file = gt_files[n];
-	    break;
-	  }
-    }
+    s->u.s.line.file = system_h_file;
 
     return s;
 }
@@ -893,7 +854,7 @@ note_variable (const char *s, type_p t,
 /* Most-general structure field creator.  */
 static pair_p
 create_field_all (pair_p next, type_p type, const char *name, options_p opt,
-		  const char *file, int line)
+		  input_file* inpf, int line)
 {
   pair_p field;
 
@@ -902,7 +863,7 @@ create_field_all (pair_p next, type_p ty
   field->type = type;
   field->name = name;
   field->opt = opt;
-  field->line.file = file;
+  field->line.file = inpf;
   field->line.line = line;
   return field;
 }
@@ -1658,8 +1619,9 @@ open_base_files (void)
    components skipped.  */
 
 static const char *
-get_file_realbasename (const char *f)
+get_file_realbasename  (const input_file *inpf)
 {
+  const char* f = get_input_file_name (inpf);
   const char * lastslash = strrchr (f, '/');
 
   return (lastslash != NULL) ? lastslash + 1 : f;
@@ -1668,26 +1630,27 @@ get_file_realbasename (const char *f)
 /* For F a filename, return the relative path to F from $(srcdir) if the
    latter is a prefix in F, NULL otherwise.  */
 
-static const char *
-get_file_srcdir_relative_path (const char *f)
+const char *
+get_file_srcdir_relative_path (const input_file *inpf)
 {
-  if (strlen (f) > srcdir_len
-      && IS_DIR_SEPARATOR (f[srcdir_len])
-      && memcmp (f, srcdir, srcdir_len) == 0)
-    return f + srcdir_len + 1;
+  const char* fname = get_input_file_name (inpf);
+  if (strlen (fname) > srcdir_len
+      && IS_DIR_SEPARATOR (fname[srcdir_len])
+      && memcmp (fname, srcdir, srcdir_len) == 0)
+    return fname + srcdir_len + 1;
   else
     return NULL;
 }
 
-/* For F a filename, return the relative path to F from $(srcdir) if the
+/* For F an input_file, return the relative path to F from $(srcdir) if the
    latter is a prefix in F, or the real basename of F otherwise.  */
 
 static const char *
-get_file_basename (const char *f)
+get_file_basename (const input_file *inpf)
 {
-  const char * srcdir_path = get_file_srcdir_relative_path (f);
+  const char * srcdir_path = get_file_srcdir_relative_path (inpf);
 
-  return (srcdir_path != NULL) ? srcdir_path : get_file_realbasename (f);
+  return (srcdir_path != NULL) ? srcdir_path : get_file_realbasename (inpf);
 }
 
 /* For F a filename, return the lang_dir_names relative index of the language
@@ -1713,19 +1676,19 @@ get_prefix_langdir_index (const char *f)
   return -1;
 }
 
-/* For F a filename, return the name of language directory where F is located,
-   if any, NULL otherwise.  */
 
+/* For INPF an input_file, return the name of language directory where
+   INPF is located, if any, NULL otherwise.  */
 static const char *
-get_file_langdir (const char *f)
+get_file_langdir (const input_file *inpf)
 {
   /* Get the relative path to F from $(srcdir) and find the language by
      comparing the prefix with language directory names.  If F is not even
      srcdir relative, no point in looking further.  */
 
   int lang_index;
-  const char * srcdir_relative_path = get_file_srcdir_relative_path (f);
-  const char * r;
+  const char *srcdir_relative_path = get_file_srcdir_relative_path (inpf);
+  const char *r;
 
   if (!srcdir_relative_path)
     return NULL;
@@ -1742,16 +1705,16 @@ get_file_langdir (const char *f)
   return r;
 }
 
-/* The gt- output file name for F.  */
+/* The gt- output file name for INPF.  */
 
 static const char *
-get_file_gtfilename (const char *f)
+get_file_gtfilename (const input_file *inpf)
 {
   /* Cook up an initial version of the gt- file name from the file real
      basename and the language name, if any.  */
 
-  const char *basename = get_file_realbasename (f);
-  const char *langdir = get_file_langdir (f);
+  const char *basename = get_file_realbasename (inpf);
+  const char *langdir = get_file_langdir (inpf);
 
   char * result =
     (langdir ? xasprintf ("gt-%s-%s", langdir, basename)
@@ -1777,7 +1740,7 @@ get_file_gtfilename (const char *f)
    INPUT_FILE.  */
 
 outf_p
-get_output_file_with_visibility (const char *input_file)
+get_output_file_with_visibility (input_file* inpf)
 {
   outf_p r;
   size_t len;
@@ -1788,30 +1751,30 @@ get_output_file_with_visibility (const c
   /* This can happen when we need a file with visibility on a
      structure that we've never seen.  We have to just hope that it's
      globally visible.  */
-  if (input_file == NULL)
-    input_file = "system.h";
+  if (inpf == NULL)
+    inpf = system_h_file;
 
-  /* In plugin mode, return NULL unless the input_file is one of the
-     plugin_files.  */
+  /* In plugin mode, return NULL unless the INPF is one of the
+     plugin_files.  We can compare input_file-s by pointer equality. */
   if (plugin_files)
     {
       size_t i;
       for (i = 0; i < nb_plugin_files; i++)
-	if (strcmp (input_file, plugin_files[i]) == 0)
+	if (inpf == plugin_files[i])
 	  return plugin_output;
 
       return NULL;
     }
 
   /* Determine the output file name.  */
-  basename = get_file_basename (input_file);
+  basename = get_file_basename (inpf);
 
   len = strlen (basename);
   if ((len > 2 && memcmp (basename+len-2, ".c", 2) == 0)
       || (len > 2 && memcmp (basename+len-2, ".y", 2) == 0)
       || (len > 3 && memcmp (basename+len-3, ".in", 3) == 0))
     {
-      output_name = get_file_gtfilename (input_file);
+      output_name = get_file_gtfilename (inpf);
       for_name = basename;
     }
   /* Some headers get used by more than one front-end; hence, it
@@ -1863,13 +1826,13 @@ get_output_file_with_visibility (const c
 }
 
 /* The name of an output file, suitable for definitions, that can see
-   declarations made in INPUT_FILE and is linked into every language
-   that uses INPUT_FILE.  */
+   declarations made in INPF and is linked into every language
+   that uses INPF.  */
 
 const char *
-get_output_file_name (const char *input_file)
+get_output_file_name (input_file *inpf)
 {
-  outf_p o =  get_output_file_with_visibility (input_file);
+  outf_p o =  get_output_file_with_visibility (inpf);
   if (o)
     return o->name;
   return NULL;
@@ -1951,7 +1914,7 @@ close_output_files (void)
 struct flist {
   struct flist *next;
   int started_p;
-  const char *name;
+  const input_file *file;
   outf_p f;
 };
 
@@ -2000,7 +1963,7 @@ static void write_local (outf_p output_h
 			 type_p param_structs);
 static void write_enum_defn (type_p structures, type_p param_structs);
 static int contains_scalar_p (type_p t);
-static void put_mangled_filename (outf_p , const char *);
+static void put_mangled_filename (outf_p , const input_file *);
 static void finish_root_table (struct flist *flp, const char *pfx,
 			       const char *tname, const char *lastname,
 			       const char *name);
@@ -2471,7 +2434,7 @@ walk_type (type_p t, struct walk_type_da
 	      {
 		fprintf (stderr,
 	"%s:%d: warning: field `%s' is missing `tag' or `default' option\n",
-			 d->line->file, d->line->line, f->name);
+			 get_input_file_name (d->line->file), d->line->line, f->name);
 		continue;
 	      }
 	    else if (union_p && ! (default_p || tagid))
@@ -2639,16 +2602,27 @@ output_type_enum (outf_p of, type_p s)
 static outf_p
 get_output_file_for_structure (const_type_p s, type_p *param)
 {
-  const char * fn = s->u.s.line.file;
+  const input_file* fn = NULL;
   int i;
 
+  if (UNION_OR_STRUCT_P (s))
+    fn = s->u.s.line.file;
+  else if (s->kind == TYPE_PARAM_STRUCT)
+    fn = s->u.param_struct.line.file;
+
+  CHECK_INPUT_FILE_MAGIC (fn);
+
   /* This is a hack, and not the good kind either.  */
   for (i = NUM_PARAM - 1; i >= 0; i--)
     if (param && param[i] && param[i]->kind == TYPE_POINTER
 	&& UNION_OR_STRUCT_P (param[i]->u.p))
       fn = param[i]->u.p->u.s.line.file;
 
-  return get_output_file_with_visibility (fn);
+  CHECK_INPUT_FILE_MAGIC (fn);
+
+  /* The call to get_output_file_with_visibility may update fn by
+     caching its result inside, so we need the CONST_CAST. */
+  return get_output_file_with_visibility (CONST_CAST(input_file*, fn));
 }
 
 /* For S, a structure that's part of ORIG_S, and using parameters
@@ -3229,9 +3203,12 @@ contains_scalar_p (type_p t)
 /* Mangle FN and print it to F.  */
 
 static void
-put_mangled_filename (outf_p f, const char *fn)
+put_mangled_filename (outf_p f, const input_file *fn)
 {
-  const char *name = get_output_file_name (fn);
+  /* The call to get_output_file_name may indirectly update fn since
+     get_output_file_with_visibility caches its result inside, so we
+     need the CONST_CAST.  */
+  const char *name = get_output_file_name (CONST_CAST (input_file*, fn));
   if (!f || !name)
     return;
   for (; *name != 0; name++)
@@ -3261,7 +3238,7 @@ finish_root_table (struct flist *flp, co
   for (fli2 = flp; fli2 && base_files; fli2 = fli2->next)
     if (fli2->started_p)
       {
-	lang_bitmap bitmap = get_lang_bitmap (fli2->name);
+	lang_bitmap bitmap = get_lang_bitmap (fli2->file);
 	int fnum;
 
 	for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
@@ -3270,7 +3247,7 @@ finish_root_table (struct flist *flp, co
 	      oprintf (base_files[fnum],
 		       "extern const struct %s gt_%s_",
 		       tname, pfx);
-	      put_mangled_filename (base_files[fnum], fli2->name);
+	      put_mangled_filename (base_files[fnum], fli2->file);
 	      oprintf (base_files[fnum], "[];\n");
 	    }
       }
@@ -3287,7 +3264,7 @@ finish_root_table (struct flist *flp, co
   for (fli2 = flp; fli2; fli2 = fli2->next)
     if (fli2->started_p)
       {
-	lang_bitmap bitmap = get_lang_bitmap (fli2->name);
+	lang_bitmap bitmap = get_lang_bitmap (fli2->file);
 	int fnum;
 
 	fli2->started_p = 0;
@@ -3296,7 +3273,7 @@ finish_root_table (struct flist *flp, co
 	  if (bitmap & 1)
 	    {
 	      oprintf (base_files[fnum], "  gt_%s_", pfx);
-	      put_mangled_filename (base_files[fnum], fli2->name);
+	      put_mangled_filename (base_files[fnum], fli2->file);
 	      oprintf (base_files[fnum], ",\n");
 	    }
       }
@@ -3632,8 +3609,8 @@ write_roots (pair_p variables, bool emit
 	  fli->f = f;
 	  fli->next = flp;
 	  fli->started_p = 0;
-	  fli->name = v->line.file;
-	  gcc_assert(fli->name);
+	  fli->file = v->line.file;
+	  gcc_assert(fli->file);
 	  flp = fli;
 
 	  oprintf (f, "\n/* GC roots.  */\n\n");
@@ -4171,8 +4148,8 @@ dump_options (int indent, options_p opt)
 static void
 dump_fileloc (int indent, struct fileloc line)
 {
-  printf ("%*cfileloc: file = %s, line = %d\n", indent, ' ', line.file,
-	  line.line);
+  printf ("%*cfileloc: file = %s, line = %d\n", indent, ' ', 
+	  get_input_file_name (line.file), line.line);
 }
 
 /* Recursively dumps the struct, union, or a language-specific
@@ -4461,12 +4438,64 @@ parse_program_options (int argc, char**a
       for  (i = 0; i < (int) nb_plugin_files; i++)
 	{
 	  char *name = argv[i + optind];
-	  plugin_files[i] = name;
+	  plugin_files[i] = input_file_by_name (name);
 	}
     }
 }
 
 
+
+/******* Manage input files. ******/
+
+/* Hash table of unique input file names.  */
+static htab_t input_file_htab;
+
+/* Find or allocate a new input_file by hash-consing it. */
+input_file* 
+input_file_by_name (const char* name)
+{
+  PTR* slot;
+  input_file* f = NULL;
+  int namlen = 0;
+  if (!name) 
+    return NULL;
+  namlen = strlen (name);
+  f = XCNEWVAR (input_file, sizeof(input_file)+namlen+2);
+  f->inpbitmap = 0;
+  f->inpoutf = NULL;
+  f->inpmagic = INPUT_FILE_MAGIC;
+  strcpy (f->inpname, name);
+  slot = htab_find_slot (input_file_htab, f, INSERT);
+  gcc_assert (slot != NULL);
+  if (*slot) { 
+    /* Already known input file. */
+    free (f);
+    return (input_file*)(*slot);
+  }
+  /* New input file. */
+  *slot = f;
+  return f;
+}
+
+/* Hash table support routines for input_file-s.  */
+static hashval_t
+htab_hash_inputfile (const void *p)
+{
+  const input_file *inpf = (const input_file *) p;
+  gcc_assert (inpf);
+  return htab_hash_string (get_input_file_name (inpf));
+}
+
+static int
+htab_eq_inputfile (const void *x, const void *y)
+{
+  const input_file *inpfx = (const input_file *) x;
+  const input_file *inpfy = (const input_file *) y;
+  gcc_assert (inpfx != NULL && inpfy != NULL);
+  return !strcmp (get_input_file_name (inpfx), get_input_file_name (inpfy));
+}
+
+
 int
 main (int argc, char **argv)
 {
@@ -4479,6 +4508,12 @@ main (int argc, char **argv)
   /* Set the scalar_is_char union number for predefined scalar types. */
   scalar_nonchar.u.scalar_is_char = FALSE;
   scalar_char.u.scalar_is_char = TRUE;
+  /* Create the hash-table used to hash-cons input files. */
+  input_file_htab = 
+    htab_create (800, htab_hash_inputfile, htab_eq_inputfile, NULL);
+  /* Initialize our special input files. */
+  this_file = input_file_by_name (__FILE__);
+  system_h_file = input_file_by_name ("system.h");
 
   parse_program_options (argc, argv);
 
@@ -4516,10 +4551,11 @@ main (int argc, char **argv)
       do_scalar_typedef ("void", &pos); pos.line++;
       do_typedef ("PTR", create_pointer (resolve_typedef ("void", &pos)), &pos);
       read_input_list (inputlist);
-      for (i = 0; i < num_gt_files; i++) {
-	parse_file (gt_files[i]);
-	DBGPRINTF ("parsed file #%d %s", (int) i, gt_files[i]);
-      }
+      for (i = 0; i < num_gt_files; i++) 
+	{
+	  parse_file (get_input_file_name (gt_files[i]));
+	  DBGPRINTF ("parsed file #%d %s", (int) i, get_input_file_name (gt_files[i]));
+	}
       DBGPRINT_COUNT_TYPE ("structures after parsing", structures);
       DBGPRINT_COUNT_TYPE ("param_structs after parsing", param_structs);
       if (verbosity_level >= 1)
@@ -4546,7 +4582,11 @@ main (int argc, char **argv)
 
       /* Parse our plugin files.  */
       for (ix = 0; ix < nb_plugin_files; ix++) 
-	parse_file (plugin_files[ix]);
+	{ 
+	  parse_file (get_input_file_name (plugin_files[ix]));
+	  DBGPRINTF ("parsed plugin file #%d %s", (int) ix, 
+		     get_input_file_name (plugin_files[ix]));
+	}
 
       if (hit_error)
 	return 1;
--- ../gengtype-gcc-02-verbosity/gengtype.h	2010-09-08 16:09:52.000000000 +0200
+++ gcc/gengtype.h	2010-09-09 16:31:09.000000000 +0200
@@ -25,13 +25,86 @@ along with GCC; see the file COPYING3.
    represented by a bitmap.  */
 typedef unsigned lang_bitmap;
 
-/* A file position, mostly for error messages.
-   The FILE element may be compared using pointer equality.  */
+/* Variable length structure representing an input file.  A hash table
+   ensure uniqueness for a given input file name.  The only function
+   allocating input_file-s is input_file_by_name. */
+struct input_file_st {
+  struct outf* inpoutf;	/* Cached corresponding output file, computed
+			   in get_output_file_with_visibility. */
+  lang_bitmap inpbitmap; /* The set of languages using this file. */
+  char inpname[1]; /* a flexible array, ended by a null char. */
+};
+typedef struct input_file_st input_file;
+
+/* Table of all input files, and its size. */
+extern input_file** gt_files;
+extern size_t num_gt_files;
+
+/* A number of places use the name of this "gengtype.c" file for a
+   location for things that we can't rely on the source to define.  We
+   also need to refer to the "system.h" file specifically.  These two
+   pointers are initialized early in main. */
+extern input_file* this_file;
+extern input_file* system_h_file;
+
+/* Retrieve or create the input_file for a given name, which is a file
+   path. This is the only function allocating input_file-s and it is
+   hash-consing them. */
+input_file* input_file_by_name (const char* name);
+
+
+/* For F an input_file, return the relative path to F from $(srcdir)
+   if the latter is a prefix in F, NULL otherwise.  */
+const char *get_file_srcdir_relative_path (const input_file *inpf);
+
+/* Get the name of an input file. */
+static inline const char* 
+get_input_file_name (const input_file *inpf)
+{
+  if (inpf) 
+    return inpf->inpname;
+  return NULL;
+}
+
+/* Return a bitmap which has bit `1 << BASE_FILE_<lang>' set iff
+   INPUT_FILE is used by <lang>.
+
+   This function should be written to assume that a file _is_ used
+   if the situation is unclear.  If it wrongly assumes a file _is_ used,
+   a linker error will result.  If it wrongly assumes a file _is not_ used,
+   some GC roots may be missed, which is a much harder-to-debug problem.
+  */
+
+static inline lang_bitmap
+get_lang_bitmap (const input_file* inpf)
+{
+  if (inpf == NULL)
+    return 0;
+  return inpf->inpbitmap;
+}
+
+/* Set the bitmap returned by get_lang_bitmap.  The only legitimate
+   callers of this function are read_input_list & read_state_*.  */
+static inline void 
+set_lang_bitmap (input_file* inpf, lang_bitmap n)
+{
+  gcc_assert (inpf);
+  inpf->inpbitmap = n;
+}
+
+/* A file position, mostly for error messages.  The FILE element may
+   be compared using pointer equality since it is hash-consed.  */
 struct fileloc {
-  const char *file;
+  input_file *file;
   int line;
 };
 
+/* Vector of per-language directories.  */
+extern const char **lang_dir_names;
+extern size_t num_lang_dirs;
+
+
+
 /* Data types handed around within, but opaque to, the lexer and parser.  */
 typedef struct pair *pair_p;
 typedef struct type *type_p;
@@ -65,10 +138,14 @@ void oprintf (outf_p o, const char *S, .
      ATTRIBUTE_PRINTF_2;
 
 /* An output file, suitable for definitions, that can see declarations
-   made in INPUT_FILE and is linked into every language that uses
-   INPUT_FILE.  May return NULL in plugin mode. */
-extern outf_p get_output_file_with_visibility
-   (const char *input_file);
+   made in INPF and is linked into every language that uses INPF.  May
+   return NULL in plugin mode. */
+outf_p get_output_file_with_visibility (input_file* inpf);
+
+/* The name of an output file, suitable for definitions, that can see
+   declarations made in INPF and is linked into every language that
+   uses INPF.  May return NULL.  */
+const char *get_output_file_name (input_file *inpf);
 
 /* Source directory.  */
 extern const char *srcdir;
--- ../gengtype-gcc-02-verbosity/gengtype-lex.l	2010-08-27 07:56:01.000000000 +0200
+++ gcc/gengtype-lex.l	2010-09-09 16:01:23.000000000 +0200
@@ -1,6 +1,6 @@
 /* -*- indented-text -*- */
 /* Process source files and output type information.
-   Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009
+   Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.
 %{
 #include "bconfig.h"
 #include "system.h"
+#include "errors.h"             /* for fatal, needed by gengtype.h */
 
 #define malloc xmalloc
 #define realloc xrealloc
@@ -202,7 +203,7 @@ yybegin (const char *fname)
       perror (fname);
       exit (1);
     }
-  lexer_line.file = fname;
+  lexer_line.file = input_file_by_name (fname);
   lexer_line.line = 1;
 }
 
--- ../gengtype-gcc-02-verbosity/gengtype-parse.c	2010-08-27 07:56:01.000000000 +0200
+++ gcc/gengtype-parse.c	2010-09-09 16:01:41.000000000 +0200
@@ -1,5 +1,5 @@
 /* Process source files and output type information.
-   Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007, 2010 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -19,6 +19,7 @@ along with GCC; see the file COPYING3.
 
 #include "bconfig.h"
 #include "system.h"
+#include "errors.h"	/* for fatal, needed by gengtype.h */
 #include "gengtype.h"
 
 /* This is a simple recursive-descent parser which understands a subset of
@@ -135,7 +136,8 @@ parse_error (const char *msg, ...)
 {
   va_list ap;
 
-  fprintf (stderr, "%s:%d: parse error: ", lexer_line.file, lexer_line.line);
+  fprintf (stderr, "%s:%d: parse error: ", 
+	   get_input_file_name (lexer_line.file), lexer_line.line);
 
   va_start (ap, msg);
   vfprintf (stderr, msg, ap);
@@ -679,6 +681,7 @@ static type_p
 type (options_p *optsp, bool nested)
 {
   const char *s;
+  static int anonymous_count; /* to generate unique pseudo-identifiers! */
   *optsp = 0;
   switch (token ())
     {
@@ -695,15 +698,15 @@ type (options_p *optsp, bool nested)
     case UNION:
       {
 	options_p opts = 0;
-    /* GTY annotations follow attribute syntax
-       GTY_BEFORE_ID is for union/struct declarations
-       GTY_AFTER_ID is for variable declarations.  */
-    enum {
-        NO_GTY,
-        GTY_BEFORE_ID,
-        GTY_AFTER_ID
-    } is_gty = NO_GTY;
-    bool is_union = (token () == UNION);
+	/* GTY annotations follow attribute syntax
+	   GTY_BEFORE_ID is for union/struct declarations
+	   GTY_AFTER_ID is for variable declarations.  */
+	enum {
+	  NO_GTY,
+	  GTY_BEFORE_ID,
+	  GTY_AFTER_ID
+	} is_gty = NO_GTY;
+	bool is_union = (token () == UNION);
 	advance ();
 
 	/* Top-level structures that are not explicitly tagged GTY(())
@@ -713,40 +716,62 @@ type (options_p *optsp, bool nested)
 	   that we can't handle.  */
 	if (nested || token () == GTY_TOKEN)
 	  {
-        is_gty = GTY_BEFORE_ID;
-        opts = gtymarker_opt ();
+	    is_gty = GTY_BEFORE_ID;
+	    opts = gtymarker_opt ();
 	  }
 
 	if (token () == ID)
 	  s = advance ();
 	else
-	  s = xasprintf ("anonymous:%s:%d", lexer_line.file, lexer_line.line);
+	  {
+	    /* We don't want to wire in the source directory (because
+	       in plugin mode, the source directory can be unavailable
+	       since gengtype has read its state).  So if the input is
+	       from GCC source directory, we use its relative path to
+	       build an anonymous unique tag.  */
+	    const char* relp = get_file_srcdir_relative_path (lexer_line.file);
+	    anonymous_count++;
+	    if (relp) 
+	      /* The input file is a GCC source file, we use a double
+		 colon after anonymous.  To be sure s is truly unique,
+		 we also use anonymous_count.  */
+	      s = xasprintf ("anonymous::%s:%d::%d", 
+			     relp, lexer_line.line, anonymous_count);
+	    else
+	      /* The input file is outside of GCC source tree, we use
+		 a single colon after anonymous.  To be sure s is
+		 truly unique, we also use anonymous_count.  */
+	      s = xasprintf ("anonymous:%s:%d::%d", 
+			     get_input_file_name (lexer_line.file), 
+			     lexer_line.line, anonymous_count);
+	      
+	  }
 
         /* Unfortunately above GTY_TOKEN check does not capture the
            typedef struct_type GTY case.  */
 	if (token () == GTY_TOKEN)
 	  {
-        is_gty = GTY_AFTER_ID;
-        opts = gtymarker_opt ();
+	    is_gty = GTY_AFTER_ID;
+	    opts = gtymarker_opt ();
 	  }
 
-    if (is_gty)
-      {
-        if (token () == '{')
-          {
-            pair_p fields;
-
-            if (is_gty == GTY_AFTER_ID)
-                parse_error ("GTY must be specified before identifier");
-
-            advance ();
-            fields = struct_field_seq ();
-            require ('}');
-            return new_structure (s, is_union, &lexer_line, fields, opts);
-          }
-      }
-    else if (token () == '{')
-      consume_balanced ('{', '}');
+	if (is_gty)
+	  {
+	    if (token () == '{')
+	      {
+		pair_p fields;
+
+		if (is_gty == GTY_AFTER_ID)
+		  parse_error ("GTY must be specified before identifier");
+
+		advance ();
+		fields = struct_field_seq ();
+		require ('}');
+		return new_structure (s, is_union, &lexer_line, fields, opts);
+	      }
+	  }
+	else if (token () == '{')
+	  consume_balanced ('{', '}');
 	if (opts)
 	  *optsp = opts;
 	return find_structure (s, is_union);
@@ -754,11 +779,22 @@ type (options_p *optsp, bool nested)
 
     case ENUM:
       advance ();
-	if (token () == ID)
-	  s = advance ();
-	else
-	  s = xasprintf ("anonymous:%s:%d", lexer_line.file, lexer_line.line);
-
+      if (token () == ID)
+	s = advance ();
+      else
+	{
+	    /* Again, we don't want to wire in the GCC source tree
+	       directory.  */
+	    const char* relp = get_file_srcdir_relative_path (lexer_line.file);
+	    anonymous_count++;
+	    if (relp) 
+	      s = xasprintf ("anonymous::%s:%d::%d", 
+			     relp, lexer_line.line, anonymous_count);
+	    else
+	      s = xasprintf ("anonymous:%s:%d::%d", 
+			     get_input_file_name (lexer_line.file), 
+			     lexer_line.line, anonymous_count);
+	}
       if (token () == '{')
 	consume_balanced ('{','}');
       return create_scalar_type (s);
