--- ../gengtype-gcc-02/gengtype.c	2010-08-29 08:17:58.000000000 +0200
+++ gcc/gengtype.c	2010-08-29 11:25:37.000000000 +0200
@@ -121,24 +121,15 @@ struct type
   || (x)->kind == TYPE_LANG_STRUCT)
 
 
-/* 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);
-const char *get_output_file_name (const char *);
-
-/* Print, like fprintf, to O.  No-op if O is NULL. */
-static void oprintf (outf_p o, const char *S, ...)
-     ATTRIBUTE_PRINTF_2;
 
 
 /* Rhe name of the file containing the list of input files. */
 static char* inputlist = 0;
 
-/* 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 that case only a single
+   file is produced.  Each element of plugin_files should have an all
+   zero lang_bitmap. */
+static input_file** plugin_files;
 static size_t nb_plugin_files;
 
 /* The generated plugin output file & name.  */
@@ -168,12 +159,12 @@ 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 const char * get_file_srcdir_relative_path (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.  */
@@ -192,8 +183,7 @@ error_at_line (const struct fileloc *pos
   va_list ap;
 
   va_start (ap, msg);
-
-  fprintf (stderr, "%s:%d: ", pos->file, pos->line);
+  fprintf (stderr, "%s:%d: ", input_file_name (pos->ifile), pos->line);
   vfprintf (stderr, msg, ap);
   fputc ('\n', stderr);
   hit_error = true;
@@ -221,13 +211,14 @@ 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 */
+input_file* this_file;
+input_file* system_h_file;
+
 
-/* 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.  */
-static const char this_file[] = __FILE__;
 
 /* Vector of per-language directories.  */
 static const char **lang_dir_names;
@@ -237,48 +228,6 @@ static size_t num_lang_dirs;
    BASE_FILES entry for each language.  */
 static outf_p *base_files;
 
-/* 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.
-
-   The relevant bitmap is stored immediately before the file's name in the
-   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)
-    /* 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;
-    }
-}
-
 /* Scan the input file, LIST, and determine how much space we need to
    store strings in.  Also, count the number of language directories
    and files.  The numbers returned are overestimates as they does not
@@ -318,9 +267,8 @@ measure_input_list (FILE *list)
 /* Read one input line from LIST to HEREP (which is updated).  A
    pointer to the string is returned via LINEP.  If it was a language
    subdirectory in square brackets, strip off the square brackets and
-   return true.  Otherwise, leave space before the string for a
-   lang_bitmap, and return false.  At EOF, returns false, does not
-   touch *HEREP, and sets *LINEP to NULL.  POS is used for
+   return true.  Otherwise return false.  At EOF, returns false, does
+   not touch *HEREP, and sets *LINEP to NULL.  POS is used for
    diagnostics.  */
 static bool
 read_input_line (FILE *list, char **herep, char **linep,
@@ -341,7 +289,7 @@ read_input_line (FILE *list, char **here
     }
   else if (c == '[')
     {
-      /* No space for a lang_bitmap is necessary.  Discard the '['. */
+      /* Discard the '['. */
       c = getc (list);
       line = here;
       while (c != ']' && c != '\n' && c != EOF)
@@ -366,9 +314,6 @@ read_input_line (FILE *list, char **here
     }
   else
     {
-      /* Leave space for a lang_bitmap.  */
-      memset (here, 0, sizeof (lang_bitmap));
-      here += sizeof (lang_bitmap);
       line = here;
       do
 	{
@@ -411,11 +356,11 @@ read_input_list (const char *listname)
       size_t nfiles = 0;
       lang_bitmap curlangs = (1 << num_lang_dirs) - 1;
 
-      epos.file = listname;
+      epos.ifile = 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 (;;)
 	{
@@ -445,9 +390,10 @@ 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)
+		if (strcmp (input_file_name (gt_files[i]), line) == 0)
 		  {
 		    /* Throw away the string we just read, and add the
 		       current language to the existing string's bitmap.  */
@@ -459,13 +405,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
@@ -547,6 +493,69 @@ static type_p find_param_structure
 static type_p adjust_field_tree_exp (type_p t, options_p opt);
 static type_p adjust_field_rtx_def (type_p t, options_p opt);
 
+
+
+
+/****************************************************************
+ * Manage input files.
+ ****************************************************************/
+
+/* Hash table of unique input file names.  */
+static htab_t input_file_htab;
+
+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);
+    }
+    /* Fresh 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 *f = (const input_file *) p;
+  gcc_assert (f);
+  return htab_hash_string (input_file_name (f));
+}
+
+static int
+htab_eq_inputfile (const void *x, const void *y)
+{
+  const input_file *fx = (const input_file *) x;
+  const input_file *fy = (const input_file *) y;
+  gcc_assert (fx != NULL && fy != NULL);
+  return !strcmp (input_file_name (fx), input_file_name (fy));
+}
+
+
+
+
+/*****************************************************************
+ * Handle types.
+ ****************************************************************/
+
 /* Define S as a typedef to T at POS.  */
 
 void
@@ -558,7 +567,7 @@ do_typedef (const char *s, type_p t, str
      macros.  Ignore any attempt to typedef CUMULATIVE_ARGS, unless it
      is coming from this file (main() sets them up with safe dummy
      definitions).  */
-  if (!strcmp (s, "CUMULATIVE_ARGS") && pos->file != this_file)
+  if (!strcmp (s, "CUMULATIVE_ARGS") && pos->ifile != this_file)
     return;
 
   for (p = typedefs; p != NULL; p = p->next)
@@ -613,13 +622,16 @@ new_structure (const char *name, int isu
 {
   type_p si;
   type_p s = NULL;
-  lang_bitmap bitmap = get_lang_bitmap (pos->file);
+  lang_bitmap bitmap = get_lang_bitmap (pos->ifile);
+
+  dbgprintf ("new_structure %s bitmap %d @ %s:%d",
+	     name, (int)bitmap, input_file_name (pos->ifile), pos->line);
 
   /* temporary kludge - gengtype doesn't handle conditionals or
      macros.  Ignore any attempt to define struct location_s, unless
      it is coming from this file (main() sets it up safely). */
   if (!strcmp (name, "location_s") && !isunion
-      && pos->file != this_file)
+      && pos->ifile != this_file)
     return find_structure (name, 0);
 
   for (si = structures; si != NULL; si = si->next)
@@ -635,7 +647,7 @@ new_structure (const char *name, int isu
 	      if (si->u.s.bitmap == bitmap)
 		s = si;
 	  }
-	else if (si->u.s.line.file != NULL && si->u.s.bitmap != bitmap)
+	else if (si->u.s.line.ifile != NULL && si->u.s.bitmap != bitmap)
 	  {
 	    ls = si;
 	    si = XCNEW (struct type);
@@ -667,7 +679,7 @@ new_structure (const char *name, int isu
       structures = s;
     }
 
-  if (s->u.s.line.file != NULL
+  if (s->u.s.line.ifile != NULL
       || (s->u.s.lang_struct && (s->u.s.lang_struct->u.s.bitmap & bitmap)))
     {
       error_at_line (pos, "duplicate definition of '%s %s'",
@@ -687,17 +699,19 @@ new_structure (const char *name, int isu
   /* Reset location_s's location to input.h so that we know where to
      write out its mark routine.  */
   if (!strcmp (name, "location_s") && !isunion
-      && pos->file == this_file)
+      && pos->ifile == 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"),
+      for (n = 0; n < num_gt_files; n++) {
+	const char* gtfilnam = input_file_name (gt_files[n]);
+	if (!strcmp (gtfilnam + strlen (gtfilnam) - strlen ("input.h"),
 		     "input.h"))
 	  {
-	    s->u.s.line.file = gt_files[n];
+	    s->u.s.line.ifile = gt_files[n];
 	    break;
 	  }
     }
+    }
 
     return s;
 }
@@ -836,7 +850,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)
+		  const char *filename, int line)
 {
   pair_p field;
 
@@ -845,7 +859,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.ifile = input_file_by_name (filename);
   field->line.line = line;
   return field;
 }
@@ -858,13 +872,14 @@ create_field_at (pair_p next, type_p typ
 		 struct fileloc *pos)
 {
   return create_field_all (next, adjust_field_type (type, opt),
-			   name, opt, pos->file, pos->line);
+			   name, opt, input_file_name (pos->ifile), 
+			   pos->line);
 }
 
 /* Create a fake field with the given type and name.  NEXT is the next
    field in the chain.  */
 #define create_field(next,type,name) \
-    create_field_all(next,type,name, 0, this_file, __LINE__)
+  create_field_all(next,type,name, 0, input_file_name (this_file), __LINE__)
 
 /* Like create_field, but the field is only valid when condition COND
    is true.  */
@@ -890,7 +905,7 @@ create_optional_field_ (pair_p next, typ
      tag that specifies the condition under which the field is valid.  */
   return create_field_all (next, union_type, name,
 			   create_option (0, "desc", cond),
-			   this_file, line);
+			   input_file_name (this_file), line);
 }
 #define create_optional_field(next,type,name,cond)	\
        create_optional_field_(next,type,name,cond,__LINE__)
@@ -1594,36 +1609,38 @@ 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 = input_file_name (inpf);
   const char * lastslash = strrchr (f, '/');
-
   return (lastslash != NULL) ? lastslash + 1 : f;
 }
 
-/* For F a filename, return the relative path to F from $(srcdir) if the
-   latter is a prefix in F, NULL otherwise.  */
+/* For F an input_file, 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)
+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 = 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
-   latter is a prefix in F, or the real basename of F otherwise.  */
+/* For F a 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
@@ -1649,18 +1666,18 @@ 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
+  /* Get the relative path to INPF from $(srcdir) and find the language by
+     comparing the prefix with language directory names.  If INPF 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 * srcdir_relative_path = get_file_srcdir_relative_path (inpf);
   const char * r;
 
   if (!srcdir_relative_path)
@@ -1678,16 +1695,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)
@@ -1709,11 +1726,11 @@ get_file_gtfilename (const char *f)
 }
 
 /* An output file, suitable for definitions, that can see declarations
-   made in INPUT_FILE and is linked into every language that uses
-   INPUT_FILE.  */
+   made in INPF and is linked into every language that uses
+   INPF.  */
 
 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;
@@ -1724,8 +1741,11 @@ 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;
+
+  gcc_assert (inpf->inpmagic == INPUT_FILE_MAGIC);
+
 
   /* In plugin mode, return NULL unless the input_file is one of the
      plugin_files.  */
@@ -1733,21 +1753,25 @@ get_output_file_with_visibility (const c
     {
       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;
     }
 
+  /* Input files cache their outf. */
+  if (inpf->inpoutf != NULL)
+    return inpf->inpoutf;
+
   /* 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
@@ -1779,8 +1803,10 @@ get_output_file_with_visibility (const c
     {
       int lang_index = get_prefix_langdir_index (basename);
 
-      if (lang_index >= 0)
+      if (lang_index >= 0) {
+	inpf->inpoutf = base_files[lang_index];
 	return base_files[lang_index];
+      }
 
       output_name = "gtype-desc.c";
       for_name = NULL;
@@ -1799,13 +1825,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;
@@ -1879,7 +1905,7 @@ close_output_files (void)
 struct flist {
   struct flist *next;
   int started_p;
-  const char *name;
+  const input_file *ifile;
   outf_p f;
 };
 
@@ -1928,7 +1954,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);
@@ -2164,7 +2190,7 @@ walk_type (type_p t, struct walk_type_da
     case TYPE_POINTER:
       {
 	if (maybe_undef_p
-	    && t->u.p->u.s.line.file == NULL)
+	    && t->u.p->u.s.line.ifile == NULL)
 	  {
 	    oprintf (d->of, "%*sgcc_assert (!%s);\n", d->indent, "", d->val);
 	    break;
@@ -2318,7 +2344,7 @@ walk_type (type_p t, struct walk_type_da
 	int seen_default_p = 0;
 	options_p o;
 
-	if (! t->u.s.line.file)
+	if (! t->u.s.line.ifile)
 	  error_at_line (d->line, "incomplete structure `%s'", t->u.s.tag);
 
 	if ((d->bitmap & t->u.s.bitmap) != d->bitmap)
@@ -2399,7 +2425,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);
+			 input_file_name (d->line->ifile), d->line->line, f->name);
 		continue;
 	      }
 	    else if (union_p && ! (default_p || tagid))
@@ -2499,13 +2525,13 @@ write_types_process_field (type_p f, con
 	    oprintf (d->of, ", gt_%sa_%s", wtd->param_prefix, d->prev_val[0]);
 
 	  if (f->u.p->kind == TYPE_PARAM_STRUCT
-	      && f->u.p->u.s.line.file != NULL)
+	      && f->u.p->u.param_struct.line.ifile != NULL)
 	    {
 	      oprintf (d->of, ", gt_e_");
 	      output_mangled_typename (d->of, f);
 	    }
 	  else if (UNION_OR_STRUCT_P (f)
-		   && f->u.p->u.s.line.file != NULL)
+		   && f->u.p->u.s.line.ifile != NULL)
 	    {
 	      oprintf (d->of, ", gt_ggc_e_");
 	      output_mangled_typename (d->of, f);
@@ -2547,12 +2573,12 @@ write_types_process_field (type_p f, con
 static void
 output_type_enum (outf_p of, type_p s)
 {
-  if (s->kind == TYPE_PARAM_STRUCT && s->u.param_struct.line.file != NULL)
+  if (s->kind == TYPE_PARAM_STRUCT && s->u.param_struct.line.ifile != NULL)
     {
       oprintf (of, ", gt_e_");
       output_mangled_typename (of, s);
     }
-  else if (UNION_OR_STRUCT_P (s) && s->u.s.line.file != NULL)
+  else if (UNION_OR_STRUCT_P (s) && s->u.s.line.ifile != NULL)
     {
       oprintf (of, ", gt_ggc_e_");
       output_mangled_typename (of, s);
@@ -2567,16 +2593,25 @@ 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.ifile;
+  else if (s->kind == TYPE_PARAM_STRUCT)
+    fn = s->u.param_struct.line.ifile;
+
+  gcc_assert (!fn || fn->inpmagic == INPUT_FILE_MAGIC);
+
   /* 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;
+      fn = param[i]->u.p->u.s.line.ifile;
 
-  return get_output_file_with_visibility (fn);
+  gcc_assert (!fn || fn->inpmagic == INPUT_FILE_MAGIC);
+
+  return get_output_file_with_visibility (CONST_CAST(input_file*, fn));
 }
 
 /* For S, a structure that's part of ORIG_S, and using parameters
@@ -2767,7 +2802,7 @@ write_types (outf_p output_header, type_
 	options_p opt;
 
 	if (s->gc_used == GC_MAYBE_POINTED_TO
-	    && s->u.s.line.file == NULL)
+	    && s->u.s.line.ifile == NULL)
 	  continue;
 
 	oprintf (output_header, "#define gt_%s_", wtd->prefix);
@@ -2802,7 +2837,7 @@ write_types (outf_p output_header, type_
 		 "extern void gt_%sx_%s (void *);\n",
 		 wtd->prefix, s->u.s.tag);
 
-	if (s->u.s.line.file == NULL)
+	if (s->u.s.line.ifile == NULL)
 	  {
 	    fprintf (stderr, "warning: structure `%s' used but not defined\n",
 		     s->u.s.tag);
@@ -2820,7 +2855,7 @@ write_types (outf_p output_header, type_
 	output_mangled_typename (output_header, s);
 	oprintf (output_header, " (void *);\n");
 
-	if (stru->u.s.line.file == NULL)
+	if (stru->u.s.line.ifile == NULL)
 	  {
 	    fprintf (stderr, "warning: structure `%s' used but not defined\n",
 		     s->u.s.tag);
@@ -2837,7 +2872,7 @@ write_types (outf_p output_header, type_
 	options_p opt;
 
 	if (s->gc_used == GC_MAYBE_POINTED_TO
-	    && s->u.s.line.file == NULL)
+	    && s->u.s.line.ifile == NULL)
 	  continue;
 	for (opt = s->u.s.opt; opt; opt = opt->next)
 	  if (strcmp (opt->name, "ptr_alias") == 0)
@@ -2859,7 +2894,7 @@ write_types (outf_p output_header, type_
       {
 	type_p *param = s->u.param_struct.param;
 	type_p stru = s->u.param_struct.stru;
-	if (stru->u.s.line.file == NULL)
+	if (stru->u.s.line.ifile == NULL)
 	  continue;
 	if (stru->kind == TYPE_LANG_STRUCT)
 	  {
@@ -2972,7 +3007,7 @@ write_local (outf_p output_header, type_
       {
 	options_p opt;
 
-	if (s->u.s.line.file == NULL)
+	if (s->u.s.line.ifile == NULL)
 	  continue;
 
 	for (opt = s->u.s.opt; opt; opt = opt->next)
@@ -3025,7 +3060,7 @@ write_local (outf_p output_header, type_
 	oprintf (output_header,
 	 "\n    (void *, void *, gt_pointer_operator, void *);\n");
 
-	if (stru->u.s.line.file == NULL)
+	if (stru->u.s.line.ifile == NULL)
 	  {
 	    fprintf (stderr, "warning: structure `%s' used but not defined\n",
 		     s->u.s.tag);
@@ -3052,7 +3087,7 @@ write_local (outf_p output_header, type_
    || (UNION_OR_STRUCT_P (s) &&						\
        (((s)->gc_used == GC_POINTED_TO)					\
 	|| ((s)->gc_used == GC_MAYBE_POINTED_TO				\
-	    && s->u.s.line.file != NULL)				\
+	    && s->u.s.line.ifile != NULL)				\
 	|| ((s)->gc_used == GC_USED					\
 	    && strncmp (s->u.s.tag, "anonymous", strlen ("anonymous"))))))
 
@@ -3108,9 +3143,9 @@ 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);
+  const char *name = get_output_file_name (CONST_CAST (input_file*, fn));
   if (!f || !name)
     return;
   for (; *name != 0; name++)
@@ -3140,7 +3175,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->ifile);
 	int fnum;
 
 	for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
@@ -3149,7 +3184,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->ifile);
 	      oprintf (base_files[fnum], "[];\n");
 	    }
       }
@@ -3166,7 +3201,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->ifile);
 	int fnum;
 
 	fli2->started_p = 0;
@@ -3175,7 +3210,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->ifile);
 	      oprintf (base_files[fnum], ",\n");
 	    }
       }
@@ -3432,7 +3467,7 @@ write_array (outf_p f, pair_p v, const s
   d.indent = 2;
   d.line = &v->line;
   d.opt = v->opt;
-  d.bitmap = get_lang_bitmap (v->line.file);
+  d.bitmap = get_lang_bitmap (v->line.ifile);
   d.param = NULL;
 
   d.prev_val[3] = prevval3 = xasprintf ("&%s", v->name);
@@ -3478,7 +3513,7 @@ write_roots (pair_p variables, bool emit
 
   for (v = variables; v; v = v->next)
     {
-      outf_p f = get_output_file_with_visibility (v->line.file);
+      outf_p f = get_output_file_with_visibility (v->line.ifile);
       struct flist *fli;
       const char *length = NULL;
       int deletable_p = 0;
@@ -3511,8 +3546,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->ifile = v->line.ifile;
+	  gcc_assert(fli->ifile && fli->ifile->inpmagic == INPUT_FILE_MAGIC);
 	  flp = fli;
 
 	  oprintf (f, "\n/* GC roots.  */\n\n");
@@ -3531,7 +3566,7 @@ write_roots (pair_p variables, bool emit
 
   for (v = variables; v; v = v->next)
     {
-      outf_p f = get_output_file_with_visibility (v->line.file);
+      outf_p f = get_output_file_with_visibility (v->line.ifile);
       struct flist *fli;
       int skip_p = 0;
       int length_p = 0;
@@ -3555,7 +3590,7 @@ write_roots (pair_p variables, bool emit
 	  fli->started_p = 1;
 
 	  oprintf (f, "EXPORTED_CONST struct ggc_root_tab gt_ggc_r_");
-	  put_mangled_filename (f, v->line.file);
+	  put_mangled_filename (f, v->line.ifile);
 	  oprintf (f, "[] = {\n");
 	}
 
@@ -3567,7 +3602,7 @@ write_roots (pair_p variables, bool emit
 
   for (v = variables; v; v = v->next)
     {
-      outf_p f = get_output_file_with_visibility (v->line.file);
+      outf_p f = get_output_file_with_visibility (v->line.ifile);
       struct flist *fli;
       int skip_p = 1;
       options_p o;
@@ -3589,7 +3624,7 @@ write_roots (pair_p variables, bool emit
 	  fli->started_p = 1;
 
 	  oprintf (f, "EXPORTED_CONST struct ggc_root_tab gt_ggc_rd_");
-	  put_mangled_filename (f, v->line.file);
+	  put_mangled_filename (f, v->line.ifile);
 	  oprintf (f, "[] = {\n");
 	}
 
@@ -3602,7 +3637,7 @@ write_roots (pair_p variables, bool emit
 
   for (v = variables; v; v = v->next)
     {
-      outf_p f = get_output_file_with_visibility (v->line.file);
+      outf_p f = get_output_file_with_visibility (v->line.ifile);
       struct flist *fli;
       const char *if_marked = NULL;
       int length_p = 0;
@@ -3633,7 +3668,7 @@ write_roots (pair_p variables, bool emit
 	  fli->started_p = 1;
 
 	  oprintf (f, "EXPORTED_CONST struct ggc_cache_tab gt_ggc_rc_");
-	  put_mangled_filename (f, v->line.file);
+	  put_mangled_filename (f, v->line.ifile);
 	  oprintf (f, "[] = {\n");
 	}
 
@@ -3649,7 +3684,7 @@ write_roots (pair_p variables, bool emit
 
   for (v = variables; v; v = v->next)
     {
-      outf_p f = get_output_file_with_visibility (v->line.file);
+      outf_p f = get_output_file_with_visibility (v->line.ifile);
       struct flist *fli;
       int length_p = 0;
       int if_marked_p = 0;
@@ -3672,7 +3707,7 @@ write_roots (pair_p variables, bool emit
 	  fli->started_p = 1;
 
 	  oprintf (f, "EXPORTED_CONST struct ggc_root_tab gt_pch_rc_");
-	  put_mangled_filename (f, v->line.file);
+	  put_mangled_filename (f, v->line.ifile);
 	  oprintf (f, "[] = {\n");
 	}
 
@@ -3684,7 +3719,7 @@ write_roots (pair_p variables, bool emit
 
   for (v = variables; v; v = v->next)
     {
-      outf_p f = get_output_file_with_visibility (v->line.file);
+      outf_p f = get_output_file_with_visibility (v->line.ifile);
       struct flist *fli;
       int skip_p = 0;
       options_p o;
@@ -3708,7 +3743,7 @@ write_roots (pair_p variables, bool emit
 	  fli->started_p = 1;
 
 	  oprintf (f, "EXPORTED_CONST struct ggc_root_tab gt_pch_rs_");
-	  put_mangled_filename (f, v->line.file);
+	  put_mangled_filename (f, v->line.ifile);
 	  oprintf (f, "[] = {\n");
 	}
 
@@ -4050,7 +4085,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,
+  printf ("%*cfileloc: file = %s, line = %d\n", indent, ' ', 
+	  input_file_name (line.ifile),
 	  line.line);
 }
 
@@ -4339,7 +4375,7 @@ 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);
 	}
     }
 }
@@ -4348,11 +4384,21 @@ int
 main (int argc, char **argv)
 {
   size_t i;
-  static struct fileloc pos = { this_file, 0 };
+  static struct fileloc pos = { NULL, 0 };
   outf_p output_header;
   /* fatal uses this */
   progname = "gengtype";
 
+  input_file_htab = 
+    htab_create (800, htab_hash_inputfile, htab_eq_inputfile, NULL);
+
+  this_file = input_file_by_name (__FILE__);
+  system_h_file = input_file_by_name ("system.h");
+
+  /* This file is for all languages! */
+  set_lang_bitmap (this_file, ~0);
+  pos.ifile = this_file;
+
   parse_program_options (argc, argv);
 
   if (read_state_filename) 
@@ -4364,16 +4410,8 @@ main (int argc, char **argv)
   if (plugin_output_filename)
     {
       plugin_output = create_file ("GCC", plugin_output_filename);
-      plugin_files = XCNEWVEC (char *, nb_plugin_files);
-      for (i = 0; i < nb_plugin_files; i++)
-      {
-        /* Place an all zero lang_bitmap before the plugin file
-	   name.  */
-        char *name = argv[i + 5];
-        int len = strlen(name) + 1 + sizeof (lang_bitmap);
-        plugin_files[i] = XCNEWVEC (char, len) + sizeof (lang_bitmap);
-        strcpy (plugin_files[i], name);
-      }
+      dbgprintf ("created plugin_output %p named %s",
+		 (void*) plugin_output, plugin_output->name);
     }
 
   dbgprintf ("inputlist %s", inputlist);
@@ -4400,7 +4438,7 @@ main (int argc, char **argv)
   do_typedef ("PTR", create_pointer (resolve_typedef ("void", &pos)), &pos);
 
   for (i = 0; i < num_gt_files; i++)
-    parse_file (gt_files[i]);
+    parse_file (input_file_name (gt_files[i]));
 
   if (hit_error)
     return 1;
--- ../gengtype-gcc-02/gengtype.h	2010-08-29 08:17:58.000000000 +0200
+++ gcc/gengtype.h	2010-08-29 11:13:49.000000000 +0200
@@ -24,10 +24,88 @@ 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. An hash table
+   ensure uniqueness for a given input file name. */
+struct input_file_st
+{
+  int inpmagic;		/* Always INPUT_FILE_MAGIC.  */
+#define INPUT_FILE_MAGIC 924599103 /* 0x371c433f */
+  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 number. */
+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. */
+extern input_file* this_file;
+extern input_file* system_h_file;
+
+
+
+/* Retrieve or create the input_file for a given name. This is the
+   only function allocating input_file-s! */
+input_file* input_file_by_name (const char* name);
+
+/* Get the name of an input file. */
+static inline const char* 
+input_file_name (const input_file *inpf)
+{
+  if (inpf) {
+#if ENABLE_CHECKING
+    if (inpf->inpmagic != INPUT_FILE_MAGIC)
+      fatal("corrupted input file %p -bad magic %d",
+	    (const void*) inpf, inpf->inpmagic);
+#endif
+    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;
+#if ENABLE_CHECKING
+    if (inpf->inpmagic != INPUT_FILE_MAGIC)
+      fatal("corrupted input file %p - bad magic %d",
+	    (const void*) inpf, inpf->inpmagic);
+#endif
+    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->inpmagic == INPUT_FILE_MAGIC);
+    inpf->inpbitmap = n;
+}
+
+
+
+/* A file location, mostly for error messages.  */
 struct fileloc {
-  const char *file;
+  input_file *ifile;
   int line;
 };
 
@@ -59,6 +137,18 @@ extern outf_p output_files;
    source file.  */
 extern outf_p header_file;
 
+
+/* 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. */
+outf_p get_output_file_with_visibility (input_file *input_file);
+
+const char *get_output_file_name (input_file *);
+
+/* Print, like fprintf, to O.  No-op if O is NULL. */
+void oprintf (outf_p o, const char *S, ...)
+     ATTRIBUTE_PRINTF_2;
+
 /* Source directory.  */
 extern const char *srcdir;
 
--- ../gengtype-gcc-02/gengtype-lex.l	2010-08-29 11:04:49.000000000 +0200
+++ gcc/gengtype-lex.l	2010-08-29 11:07:30.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,8 @@ along with GCC; see the file COPYING3.
 %{
 #include "bconfig.h"
 #include "system.h"
+#include "errors.h"             /* for fatal */
+ 
 
 #define malloc xmalloc
 #define realloc xrealloc
@@ -202,7 +204,7 @@ yybegin (const char *fname)
       perror (fname);
       exit (1);
     }
-  lexer_line.file = fname;
+  lexer_line.ifile = input_file_by_name (fname);
   lexer_line.line = 1;
 }
 
--- ../gengtype-gcc-02/gengtype-parse.c	2010-08-29 11:04:49.000000000 +0200
+++ gcc/gengtype-parse.c	2010-08-29 11:13:38.000000000 +0200
@@ -19,6 +19,7 @@ along with GCC; see the file COPYING3.
 
 #include "bconfig.h"
 #include "system.h"
+#include "errors.h"	/* for fatal */
 #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: ", 
+	   input_file_name (lexer_line.ifile), lexer_line.line);
 
   va_start (ap, msg);
   vfprintf (stderr, msg, ap);
@@ -720,7 +722,8 @@ type (options_p *optsp, bool nested)
 	if (token () == ID)
 	  s = advance ();
 	else
-	  s = xasprintf ("anonymous:%s:%d", lexer_line.file, lexer_line.line);
+	  s = xasprintf ("anonymous:%s:%d", 
+			 input_file_name (lexer_line.ifile), lexer_line.line);
 
         /* Unfortunately above GTY_TOKEN check does not capture the
            typedef struct_type GTY case.  */
@@ -757,7 +760,8 @@ type (options_p *optsp, bool nested)
 	if (token () == ID)
 	  s = advance ();
 	else
-	  s = xasprintf ("anonymous:%s:%d", lexer_line.file, lexer_line.line);
+	  s = xasprintf ("anonymous:%s:%d", 
+			 input_file_name (lexer_line.ifile), lexer_line.line);
 
       if (token () == '{')
 	consume_balanced ('{','}');
@@ -904,8 +908,8 @@ def_vec_alloc (void)
   note_def_vec_alloc (type, astrat, &lexer_line);
 }
 
-/* Parse the file FNAME for GC-relevant declarations and definitions.
-   This is the only entry point to this file.  */
+/* Parse the input file named FNAME for GC-relevant declarations and
+   definitions.  This is the only entry point to this file.  */
 void
 parse_file (const char *fname)
 {
--- ../gengtype-gcc-02/Makefile.in	2010-08-28 19:17:07.000000000 +0200
+++ gcc/Makefile.in	2010-08-29 12:06:49.000000000 +0200
@@ -3887,9 +3887,10 @@ build/genextract.o : genextract.c $(RTL_
 build/genflags.o : genflags.c $(RTL_BASE_H) $(OBSTACK_H) $(BCONFIG_H)	\
   $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h
 build/gengenrtl.o : gengenrtl.c $(BCONFIG_H) $(SYSTEM_H) rtl.def
-build/gengtype-lex.o : gengtype-lex.c gengtype.h $(BCONFIG_H) $(SYSTEM_H)
+build/gengtype-lex.o : gengtype-lex.c gengtype.h $(BCONFIG_H) $(SYSTEM_H) \
+                       errors.h
 build/gengtype-parse.o : gengtype-parse.c gengtype.h $(BCONFIG_H)	\
-  $(SYSTEM_H)
+  $(SYSTEM_H) errors.h
 build/gengtype.o : gengtype.c $(BCONFIG_H) $(SYSTEM_H) gengtype.h 	\
   rtl.def insn-notes.def errors.h double-int.h $(HASHTAB_H)
 
