This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

fyi: gengtype patches checked in


I attach all the patches as actually applied.  Ian approved everything
with a few modifications requested, which I have done; also, when
going through the new parser adding comments I found a bug (parse
errors would not halt the build) which I fixed, and I have updated
install.texi to indicate that Bison is not required unless one wishes
to build treelang.  The ChangeLogs embedded in the patches may not be
100% consistent with the actual text in the ChangeLog file or the
commit logs.

zw
Subject: Remove Yacc support

There is no longer any front end that requires gengtype to process the
Yacc union.  In fact, the only front end that still has a yacc-based
parser is treelang, and it doesn't have any GTY-tagged types or roots
at all in its parser.

	* gengtype-lex.l: Remove all rules and states relating to yacc
        input files.
	* gengtype-yacc.y: Similarly.
	* gengtype.c (note_yacc_type): Delete function.
	* gengtype.h: Update prototypes.

Index: S-vn-gtsmall/gcc/gengtype-lex.l
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype-lex.l	2007-03-22 17:24:42.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype-lex.l	2007-03-22 17:24:55.000000000 -0700
@@ -57,7 +57,7 @@
 IWORD	short|long|(un)?signed|char|int|HOST_WIDE_INT|HOST_WIDEST_INT|bool|size_t|BOOL_BITFIELD
 ITYPE	{IWORD}({WS}{IWORD})*
 
-%x in_struct in_struct_comment in_comment in_yacc_escape
+%x in_struct in_struct_comment in_comment
 %option warn noyywrap nounput nodefault perf-report
 %option 8bit never-interactive
 %%
@@ -233,12 +233,6 @@
   return ENT_EXTERNSTATIC;
 }
 
-^"%union"{WS}"{"{WS}/"GTY" {
-  BEGIN(in_struct);
-  update_lineno (yytext, yyleng);
-  return ENT_YACCUNION;
-}
-
 ^"DEF_VEC_"[[:alnum:]_]*{WS}?"("{WS}?{ID}{WS}?(","{WS}?{ID}{WS}?)*")" {
   char *macro, *arg;
   unsigned macro_len, arg_len;
@@ -279,8 +273,6 @@
 
 "/*"				{ BEGIN(in_struct_comment); }
 
-^"%{"				{ BEGIN(in_yacc_escape); } /* } */
-
 {WS}				{ update_lineno (yytext, yyleng); }
 
 "const"/[^[:alnum:]_]		/* don't care */
@@ -342,10 +334,6 @@
   yylval.s = (const char *) xmemdup (yytext+1, yyleng-2, yyleng-1);
   return ARRAY;
 }
-^"%"{ID}			{
-  yylval.s = (const char *) xmemdup (yytext+1, yyleng-1, yyleng);
-  return PERCENT_ID;
-}
 "'"("\\".|[^\\])"'"		{
   yylval.s = (const char *) xmemdup (yytext+1, yyleng-2, yyleng);
   return CHAR;
@@ -362,11 +350,6 @@
   return yytext[0];
 }
 
-^"%%"				{
-  BEGIN(INITIAL);
-  return PERCENTPERCENT;
-}
-
 "#define"[^\n]*\n		{lexer_line.line++;}
 
 .				{
@@ -391,19 +374,6 @@
 <in_comment>"*/"	{ BEGIN(INITIAL); } 
 <in_struct_comment>"*/"	{ BEGIN(in_struct); }
 
-<in_yacc_escape>{
-\n		{ lexer_line.line++; }
-[^%]{16}	|
-[^%]		/* do nothing */
-"%"/[^}]	/* do nothing */
-"%}"		{ BEGIN(in_struct); }
-"%"		{
-  error_at_line (&lexer_line, 
-		 "unterminated %%{; unexpected EOF");
-}
-}
-
-
 ["/]    		|
 <in_struct_comment,in_comment>"*"	{
   error_at_line (&lexer_line, 
Index: S-vn-gtsmall/gcc/gengtype-yacc.y
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype-yacc.y	2007-03-22 17:24:42.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype-yacc.y	2007-03-22 17:24:55.000000000 -0700
@@ -38,7 +38,6 @@
 %token <t>ENT_TYPEDEF_STRUCT
 %token <t>ENT_STRUCT
 %token ENT_EXTERNSTATIC
-%token ENT_YACCUNION
 %token GTY_TOKEN
 %token UNION
 %token STRUCT
@@ -47,15 +46,13 @@
 %token NESTED_PTR
 %token <s>PARAM_IS
 %token NUM
-%token PERCENTPERCENT "%%"
 %token <t>SCALAR
 %token <s>ID
 %token <s>STRING
 %token <s>ARRAY
-%token <s>PERCENT_ID
 %token <s>CHAR
 
-%type <p> struct_fields yacc_ids yacc_typematch
+%type <p> struct_fields
 %type <t> type lasttype
 %type <o> optionsopt options option optionseq optionseqopt
 %type <s> type_option stringseq
@@ -65,7 +62,7 @@
 start: /* empty */
        | typedef_struct start
        | externstatic start
-       | yacc_union start
+       | start
        ;
 
 typedef_struct: ENT_TYPEDEF_STRUCT options '{' struct_fields '}' ID
@@ -116,72 +113,6 @@
 	   | '='
 	   ;
 
-yacc_union: ENT_YACCUNION options struct_fields '}' yacc_typematch
-	    PERCENTPERCENT
-	      {
-	        note_yacc_type ($2, $3, $5, &lexer_line);
-	      }
-	    ;
-
-yacc_typematch: /* empty */
-		   { $$ = NULL; }
-		| yacc_typematch PERCENT_ID yacc_ids
-		   {
-		     pair_p p;
-		     for (p = $3; p->next != NULL; p = p->next)
-		       {
-		         p->name = NULL;
-			 p->type = NULL;
-		       }
-		     p->name = NULL;
-		     p->type = NULL;
-		     p->next = $1;
-		     $$ = $3;
-		   }
-		| yacc_typematch PERCENT_ID '<' ID '>' yacc_ids
-		   {
-		     pair_p p;
-		     type_p newtype = NULL;
-		     if (strcmp ($2, "type") == 0)
-		       newtype = (type_p) 1;
-		     for (p = $6; p->next != NULL; p = p->next)
-		       {
-		         p->name = $4;
-		         p->type = newtype;
-		       }
-		     p->name = $4;
-		     p->next = $1;
-		     p->type = newtype;
-		     $$ = $6;
-		   }
-		;
-
-yacc_ids: /* empty */
-	{ $$ = NULL; }
-     | yacc_ids ID
-        {
-	  pair_p p = XCNEW (struct pair);
-	  p->next = $1;
-	  p->line = lexer_line;
-	  p->opt = XNEW (struct options);
-	  p->opt->name = "tag";
-	  p->opt->next = NULL;
-	  p->opt->info = (char *)$2;
-	  $$ = p;
-	}
-     | yacc_ids CHAR
-        {
-	  pair_p p = XCNEW (struct pair);
-	  p->next = $1;
-	  p->line = lexer_line;
-	  p->opt = XNEW (struct options);
-	  p->opt->name = "tag";
-	  p->opt->next = NULL;
-	  p->opt->info = xasprintf ("'%s'", $2);
-	  $$ = p;
-	}
-     ;
-
 struct_fields: { $$ = NULL; }
 	       | type optionsopt ID bitfieldopt ';' struct_fields
 	          {
Index: S-vn-gtsmall/gcc/gengtype.c
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype.c	2007-03-22 17:24:42.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype.c	2007-03-22 17:24:55.000000000 -0700
@@ -810,65 +810,6 @@
   return t;
 }
 
-/* Create a union for YYSTYPE, as yacc would do it, given a fieldlist FIELDS
-   and information about the correspondence between token types and fields
-   in TYPEINFO.  POS is used for error messages.  */
-
-void
-note_yacc_type (options_p o, pair_p fields, pair_p typeinfo,
-		struct fileloc *pos)
-{
-  pair_p p;
-  pair_p *p_p;
-
-  for (p = typeinfo; p; p = p->next)
-    {
-      pair_p m;
-
-      if (p->name == NULL)
-	continue;
-
-      if (p->type == (type_p) 1)
-	{
-	  pair_p pp;
-	  int ok = 0;
-
-	  for (pp = typeinfo; pp; pp = pp->next)
-	    if (pp->type != (type_p) 1
-		&& strcmp (pp->opt->info, p->opt->info) == 0)
-	      {
-		ok = 1;
-		break;
-	      }
-	  if (! ok)
-	    continue;
-	}
-
-      for (m = fields; m; m = m->next)
-	if (strcmp (m->name, p->name) == 0)
-	  p->type = m->type;
-      if (p->type == NULL)
-	{
-	  error_at_line (&p->line,
-			 "couldn't match fieldname `%s'", p->name);
-	  p->name = NULL;
-	}
-    }
-
-  p_p = &typeinfo;
-  while (*p_p)
-    {
-      pair_p p = *p_p;
-
-      if (p->name == NULL
-	  || p->type == (type_p) 1)
-	*p_p = p->next;
-      else
-	p_p = &p->next;
-    }
-
-  do_typedef ("YYSTYPE", new_structure ("yy_union", 1, pos, typeinfo, o), pos);
-}
 
 static void set_gc_used_type (type_p, enum gc_used_enum, type_p *);
 static void set_gc_used (pair_p);
Index: S-vn-gtsmall/gcc/gengtype.h
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype.h	2007-03-22 17:24:42.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype.h	2007-03-22 17:24:55.000000000 -0700
@@ -144,8 +144,6 @@
 extern type_p adjust_field_type (type_p, options_p);
 extern void note_variable (const char *s, type_p t, options_p o,
 			   struct fileloc *pos);
-extern void note_yacc_type (options_p o, pair_p fields,
-			    pair_p typeinfo, struct fileloc *pos);
 
 /* Lexer and parser routines, most automatically generated.  */
 extern int yylex (void);
Subject: Remove PARAMS support

More dead wood.  PARAMS has not been used since 2003.

	* gengtype-lex.l: Remove rules for parsing pointer-to-function
        typedefs that use the old PARAMS macro.

Index: S-vn-gtsmall/gcc/gengtype-lex.l
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype-lex.l	2007-03-22 17:24:55.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype-lex.l	2007-03-22 17:24:59.000000000 -0700
@@ -129,23 +129,6 @@
   update_lineno (yytext, yyleng);
 }
 
-[^[:alnum:]_]typedef{WS}{ID}{WS}{ID}{WS}PARAMS {
-  char *namestart;
-  size_t namelen;
-  struct type *t;
-
-  for (namestart = yytext + yyleng - 7; ISSPACE (*namestart); namestart--)
-    ;
-  for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++)
-    ;
-  namestart -= namelen - 1;
-
-  t = create_scalar_type ("function type", sizeof ("function type")-1);
-  do_typedef ((const char *) xmemdup (namestart, namelen, namelen+1), t,
-	      &lexer_line);
-  update_lineno (yytext, yyleng);
-}
-
 [^[:alnum:]_]typedef{WS}{ID}{WS}{ID}{WS}"(" {
   char *namestart;
   size_t namelen;
@@ -163,23 +146,6 @@
   update_lineno (yytext, yyleng);
 }
 
-[^[:alnum:]_]typedef{WS}{ID}{WS}?"*"?{WS}?"("{WS}?"*"{WS}?{ID}{WS}?")"{WS}?PARAMS {
-  char *namestart;
-  size_t namelen;
-  struct type *t;
-
-  for (namestart = yytext + yyleng - 7; !ISIDNUM (*namestart); namestart--)
-    ;
-  for (namelen = 1; ISIDNUM (namestart[-namelen]); namelen++)
-    ;
-  namestart -= namelen - 1;
-
-  t = create_scalar_type ("function type", sizeof ("function type")-1);
-  do_typedef ((const char *) xmemdup (namestart, namelen, namelen+1), t,
-	      &lexer_line);
-  update_lineno (yytext, yyleng);
-}
-
 [^[:alnum:]_]typedef{WS}{ID}{WS}?"*"?{WS}?"("{WS}?"*"{WS}?{ID}{WS}?")"{WS}?"(" {
   char *namestart;
   size_t namelen;
Subject: Improve kludges for VEC handling

This patch may be somewhat more controversial.  It wipes out the
existing logic for handling VEC types in gengtype (which made some
pretensions to being general) and replaces it with hardcoded logic
mostly within gengtype.c.  The up side of this is that we get rid of
the confusing "macro expansion" goo within gengtype-lex.l, we replace
a number of messy lexical rules with simpler ones, and there are no
longer any #if IN_GENGTYPE blocks inside vec.h.  The down side is that
gengtype now has to be updated by hand to take account of changes to
the types defined by the VEC macros.

In the original plan, this was to be a temporary state of affairs
until gengtype was wired up to cpplib, at which point it could do
*real* macro expansion and would not need to have any hardcoded
knowledge of the innards of VECs.  I claim that even if that never
happens, the state of affairs after this patch is superior to the
state of affairs beforehand, because only a few categories of changes
to vec.h will actually require changing gengtype, and it's unlikely
that anyone will make such changes now that the VEC API has
stabilized; whereas beforehand, any modification to vec.h caused
gengtype to be recompiled.  Furthermore, if it is necessary to change
gengtype, the new code is much easier to comprehend than the old
code.  And finally, in this state no one can possibly be confused into
thinking that gengtype actually has a macro expander inside.

I had to update dependencies in the Makefile anyway, so this patch
also includes the removal of all unnecessary #includes from all the
files comprising gengtype.  In particular, none of them contain any
uses of the things defined in coretypes.h nor tm.h.

        * vec.h: Remove all #if IN_GENGTYPE blocks.
	Add comment saying that changes may require adjustments to gengtype.
        * gengtype.c: Don't include coretypes.h or tm.h.
	Add comment to inclusion of errors.h.
	(note_def_vec, note_def_vec_alloc): New functions.
	* gengtype.h: Declare new functions.
	* gengtype-lex.l: Don't include coretypes.h.
	(YY_INPUT, macro_input, push_macro_expansion, mangle_macro_name):
	Delete.
	(update_lineno): Remove unnecessary prototype.
	(DEF_VEC_* rules): Simplify using note_def_vec / note_def_vec_alloc.
	(VEC rule): Just return VEC_TOKEN.
	* gengtype-yacc.y (VEC_TOKEN): New token type.
	(type): Add a production for VEC(a,b).
	* Makefile.in: Update dependencies.

Index: S-vn-gtsmall/gcc/gengtype-lex.l
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype-lex.l	2007-03-22 17:24:59.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype-lex.l	2007-03-22 17:26:21.000000000 -0700
@@ -21,7 +21,6 @@
 
 %{
 #include "bconfig.h"
-#include "coretypes.h"
 #include "system.h"
 
 #define malloc xmalloc
@@ -30,15 +29,6 @@
 #include "gengtype.h"
 #include "gengtype-yacc.h"
 
-#define YY_INPUT(BUF,RESULT,SIZE) ((RESULT) = macro_input (BUF,SIZE))
-
-static unsigned macro_input (char *buffer, unsigned);
-static const char *push_macro_expansion (const char *, unsigned,
-					 const char *, unsigned);
-static char *mangle_macro_name (const char *, unsigned,
-       			        const char *, unsigned);
-static void update_lineno (const char *l, size_t len);
-
 struct fileloc lexer_line;
 int lexer_toplevel_done;
 
@@ -199,40 +189,58 @@
   return ENT_EXTERNSTATIC;
 }
 
-^"DEF_VEC_"[[:alnum:]_]*{WS}?"("{WS}?{ID}{WS}?(","{WS}?{ID}{WS}?)*")" {
-  char *macro, *arg;
-  unsigned macro_len, arg_len;
-  char *ptr = yytext;
-  const char *additional;
-  type_p t;
-
-  /* Find the macro name.  */
-  for (macro = ptr; *ptr != '(' && !ISSPACE (*ptr); ptr++)
-    continue;
-  for (macro_len = ptr - macro; !(ISALNUM (*ptr) || *ptr == '_'); ptr++)
-    continue;
-
-  /* Find the argument(s).  */
-  for (arg = ptr; *ptr != ')'; ptr++)
-    continue;
-  arg_len = ptr - arg;
-
-  /* Create the struct and typedef.  */
-  ptr = mangle_macro_name ("VEC", 3, arg, arg_len);
-
-  t = find_structure (ptr, 0);
-  do_typedef (ptr, t, &lexer_line);
-
-  /* Push the macro for later expansion.  */
-  additional = push_macro_expansion (macro, macro_len, arg, arg_len);
+^"DEF_VEC_"[IPO]{WS}?"("{WS}?{ID}{WS}?")" {
+  /* Definition of a generic VEC structure.  If the letter after
+     DEF_VEC_ is "I", the structure definition is slightly different
+     than if it is "P" or "O".  */
+
+  char *p = yytext + sizeof("DEF_VEC_") - 1;
+  char *q;
+  const char *type;
+  bool is_I = (*p == 'I');
+
+  /* Extract the argument to the macro.  */
+  p++;
+  while (!ISALNUM(*p) && *p != '_')
+    p++;
+  q = p;
+  while (ISALNUM(*q) || *q == '_')
+    ++;
+  type = xmemdup (p, q - p, q - p + 1);
+
+  note_def_vec (type, is_I, &lexer_line);
+  note_def_vec_alloc (type, "none", &lexer_line);
+}
+
+^"DEF_VEC_ALLOC_"[IPO]{WS}?"("{WS}?{ID}{WS}?","{WS}?{ID}{WS}?")" {
+  /* Definition of an allocation strategy for a VEC structure.  For
+     purposes of gengtype, this just declares a wrapper structure.  */
+
+  char *p = yytext + sizeof("DEF_VEC_ALLOC_I") - 1;
+  char *q;
+  char *type, *astrat;
+
+  /* Extract the two arguments to the macro.  */
+  while (!ISALNUM(*p) && *p != '_')
+    p++;
+  q = p;
+  while (ISALNUM(*q) || *q == '_')
+    q++;
+  type = alloca (q - p + 1);
+  memcpy (type, p, q - p);
+  type[q - p] = '\0';
+  p = q;
+
+  while (!ISALNUM(*p) && *p != '_')
+    p++;
+  q = p;
+  while (ISALNUM(*q) || *q == '_')
+    q++;
+  astrat = alloca (q - p + 1);
+  memcpy (astrat, p, q - p);
+  astrat[q - p] = '\0';
 
-  if (additional)
-    {
-      ptr = mangle_macro_name (ptr, strlen (ptr),
-			       additional, strlen (additional));
-      t = find_structure (ptr, 0);
-      do_typedef (ptr, t, &lexer_line);
-    }
+  note_def_vec_alloc (type, astrat, &lexer_line);
 }
 
 <in_struct>{
@@ -243,6 +251,7 @@
 
 "const"/[^[:alnum:]_]		/* don't care */
 "GTY"/[^[:alnum:]_]		{ return GTY_TOKEN; }
+"VEC"/[^[:alnum:]_]		{ return VEC_TOKEN; }
 "union"/[^[:alnum:]_]		{ return UNION; }
 "struct"/[^[:alnum:]_]		{ return STRUCT; }
 "enum"/[^[:alnum:]_]		{ return ENUM; }
@@ -266,26 +275,6 @@
   return SCALAR;
 }
 
-"VEC"{WS}?"("{WS}?{ID}{WS}?(","{WS}?{ID}{WS}?)*")" {
-  char *macro, *arg;
-  unsigned macro_len, arg_len;
-  char *ptr = yytext;
-
-  /* Find the macro name */
-  for (macro = ptr; *ptr != '(' && !ISSPACE (*ptr); ptr++)
-    continue;
-  for (macro_len = ptr - macro; !(ISALNUM(*ptr) || *ptr == '_'); ptr++)
-    continue;
-
-  /* Find the arguments.  */
-  for (arg = ptr; *ptr != ')'; ptr++)
-    continue;
-  arg_len = ptr - arg;
-
-  ptr = mangle_macro_name (macro, macro_len, arg, arg_len);
-  yylval.s = ptr;
-  return ID;
-}
 
 {ID}/[^[:alnum:]_]		{
   yylval.s = (const char *) xmemdup (yytext, yyleng, yyleng+1);
@@ -353,176 +342,6 @@
 
 %%
 
-/* Deal with the expansion caused by the DEF_VEC_x macros.  */
-
-/* Mangle a macro and argument list as done by cpp concatenation in
-   the compiler proper.  */
-static char *
-mangle_macro_name (const char *macro, unsigned macro_len,
-		   const char *arg, unsigned arg_len)
-{
-  char *ptr = (char *) xmemdup (macro, macro_len, macro_len + arg_len + 2);
-
-  /* Now copy and concatenate each argument */
-  while (arg_len)
-    {
-      ptr[macro_len++] = '_';
-      for (; arg_len && (ISALNUM(*arg) || *arg == '_'); arg_len--)
-        ptr[macro_len++] = *arg++;
-      for (; arg_len && !(ISALNUM(*arg) || *arg == '_'); arg_len--)
-        arg++;
-    }
-  ptr[macro_len] = 0;
-
-  return ptr;
-}
-
-typedef struct macro_def
-{
-  const char *name;
-  const char *expansion;
-  const char *additional;
-} macro_def_t;
-
-typedef struct macro
-{
-  const macro_def_t *def;
-  struct macro *next;
-  const char *args[10];
-} macro_t;
-
-static const macro_def_t macro_defs[] = 
-{
-#define IN_GENGTYPE 1
-#include "vec.h"
-  {NULL, NULL, NULL}
-};
-
-/* Chain of macro expansions to do at end of scanning.  */
-static macro_t *macro_expns;
-static macro_t *macro_expns_end;
-
-/* Push macro NAME (NAME_LEN) with argument ARG (ARG_LEN) onto the
-   expansion queue.  We ensure NAME is known at this point.  */
-
-static const char *
-push_macro_expansion (const char *name, unsigned name_len,
-		      const char *arg, unsigned arg_len)
-{
-  unsigned ix;
-
-  for (ix = 0; macro_defs[ix].name; ix++)
-    if (strlen (macro_defs[ix].name) == name_len
-        && !memcmp (name, macro_defs[ix].name, name_len))
-      {
-        macro_t *expansion = XNEW (macro_t);
-        char *args;
-	unsigned argno, last_arg;
-
-	expansion->def = &macro_defs[ix];
-	expansion->next = NULL;
-	args = (char *) xmemdup (arg, arg_len, arg_len+1);
-	args[arg_len] = 0;
-        for (argno = 0; *args;)
-	  {
-   	    expansion->args[argno++] = args;
-	    while (*args && (ISALNUM (*args) || *args == '_'))
-	      args++;
-	    if (argno == 1)
-	      expansion->args[argno++] = "base";
-	    if (!*args)
-	      break;
-	    *args++ = 0;
-	    while (*args && !(ISALNUM (*args) || *args == '_'))
-	      args++;
-          }
-	last_arg = argno;
-        for (; argno != 10; argno++)
-	  expansion->args[argno] = NULL;
-	if (macro_expns_end)
-          macro_expns_end->next = expansion;
-	else
-	  macro_expns = expansion;
-	macro_expns_end = expansion;
-	if (macro_defs[ix].additional)
-	  {
-	    macro_t *expn2 = XNEW (macro_t);
-            memcpy (expn2, expansion, sizeof (*expn2));
-	    expansion = expn2;
-	    expansion->def += 1;
-	    expansion->args[last_arg++] = macro_defs[ix].additional;
-	    macro_expns_end->next = expansion;
-	    macro_expns_end = expansion;
-	  }
-        if (last_arg > 2 && strcmp (expansion->args[last_arg - 1], "heap"))
-	  expansion->args[last_arg++] = "GTY (())";
-	return macro_defs[ix].additional;
-      }
-  error_at_line (&lexer_line, "unrecognized macro `%.*s(%.*s)'",
-		 name_len, name, arg_len, arg);
-  return NULL;
-}
-
-/* Attempt to read some input.  Use fread until we're at the end of
-   file.  At end of file expand the next queued macro.  We presume the
-   buffer is large enough for the entire expansion.  */
-
-static unsigned
-macro_input (char *buffer, unsigned size)
-{
-  unsigned result;
-
-  result = fread (buffer, 1, size, yyin);
-  if (result)
-    /*NOP*/;
-  else if (ferror (yyin))
-    YY_FATAL_ERROR ("read of source file failed");
-  else if (macro_expns)
-    {
-      const char *expn;
-      unsigned len;
-
-      for (expn = macro_expns->def->expansion; *expn; expn++)
-        {
-	  if (*expn == '#')
-	    {
-	      int argno;
-
-	      argno = expn[1] - '0';
-	      expn += 1;
-
-	      /* Remove inserted space? */
-	      if (buffer[result-1] == ' ' && buffer[result-2] == '_')
-	        result--;
-
-	      /* Insert the argument value */
-	      if (macro_expns->args[argno])
-	        {
-		  len = strlen (macro_expns->args[argno]);
-		  memcpy (&buffer[result], macro_expns->args[argno], len);
-		  result += len;
-		}
-
-	      /* Skip next space? */
-	      if (expn[1] == ' ' && expn[2] == '_')
-	        expn++;
-	    }
-	  else
-	    {
-	      buffer[result++] = *expn;
-	      if (*expn == ';' || *expn == '{')
-	        buffer[result++] = '\n';
-	    }
-        }
-      if (result > size)
-        YY_FATAL_ERROR ("buffer too small to expand macro");
-      macro_expns = macro_expns->next;
-      if (!macro_expns)
-        macro_expns_end = NULL;
-    }
-  return result;
-}
-
 void
 yyerror (const char *s)
 {
Index: S-vn-gtsmall/gcc/gengtype.c
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype.c	2007-03-22 17:24:55.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype.c	2007-03-22 17:25:01.000000000 -0700
@@ -21,11 +21,9 @@
 
 #include "bconfig.h"
 #include "system.h"
-#include "coretypes.h"
-#include "tm.h"
 #include "gengtype.h"
 #include "gtyp-gen.h"
-#include "errors.h"
+#include "errors.h"	/* for fatal */
 
 /* Nonzero iff an error has occurred.  */
 static int hit_error = 0;
@@ -2996,6 +2994,86 @@
 		     "gt_pch_scalar_rtab");
 }
 
+/* Record the definition of a generic VEC structure, as if we had expanded
+   the macros in vec.h:
+
+   typedef struct VEC_<type>_base GTY(()) {
+   unsigned num;
+   unsigned alloc;
+   <type> GTY((length ("%h.num"))) vec[1];
+   } VEC_<type>_base
+
+   where the GTY(()) tags are only present if is_scalar is _false_.  */
+
+void
+note_def_vec (const char *typename, bool is_scalar, struct fileloc *pos)
+{
+  pair_p f, fields;
+  type_p t;
+  options_p o;
+  const char *name = concat ("VEC_", typename, "_base", (char *)0);
+
+  if (is_scalar)
+    {
+      t = create_scalar_type (typename, strlen (typename));
+      o = 0;
+    }
+  else
+    {
+      t = resolve_typedef (typename, pos);
+      o = create_option (0, "length", "%h.num");
+    }
+
+  /* We assemble the field list in reverse order.  */
+  f = XNEW (struct pair);
+  f->type = adjust_field_type (create_array (t, "1"), o);
+  f->name = "vec";
+  f->opt = o;
+  f->line = *pos;
+  f->next = 0;
+  fields = f;
+
+  f = XNEW (struct pair);
+  f->type = adjust_field_type (create_scalar_type ("unsigned", 8), 0);
+  f->name = "alloc";
+  f->opt = 0;
+  f->line = *pos;
+  f->next = fields;
+  fields = f;
+
+  f = XNEW (struct pair);
+  f->type = adjust_field_type (create_scalar_type ("unsigned", 8), 0);
+  f->name = "num";
+  f->opt = 0;
+  f->line = *pos;
+  f->next = fields;
+  fields = f;
+
+  do_typedef (name, new_structure (name, 0, pos, fields, 0), pos);
+}
+
+/* Record the definition of an allocation-specific VEC structure, as if
+   we had expanded the macros in vec.h:
+
+   typedef struct VEC_<type>_<astrat> {
+     VEC_<type>_base base;
+   } VEC_<type>_<astrat>;
+*/
+void
+note_def_vec_alloc (const char *type, const char *astrat, struct fileloc *pos)
+{
+  const char *astratname = concat ("VEC_", type, "_", astrat, (char *)0);
+  const char *basename = concat ("VEC_", type, "_base", (char *)0);
+
+  pair_p field = XNEW (struct pair);
+  field->name = "base";
+  field->type = adjust_field_type (resolve_typedef (basename, pos), 0);
+  field->line = *pos;
+  field->next = 0;
+
+  do_typedef (astratname, new_structure (astratname, 0, pos, field, 0), pos);
+}
+
 
 extern int main (int argc, char **argv);
 int
Index: S-vn-gtsmall/gcc/gengtype.h
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype.h	2007-03-22 17:24:55.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype.h	2007-03-22 17:25:01.000000000 -0700
@@ -144,6 +144,10 @@
 extern type_p adjust_field_type (type_p, options_p);
 extern void note_variable (const char *s, type_p t, options_p o,
 			   struct fileloc *pos);
+extern void note_def_vec (const char *typename, bool is_scalar,
+			  struct fileloc *pos);
+extern void note_def_vec_alloc (const char *type, const char *astrat,
+				struct fileloc *pos);
 
 /* Lexer and parser routines, most automatically generated.  */
 extern int yylex (void);
Index: S-vn-gtsmall/gcc/vec.h
===================================================================
--- S-vn-gtsmall.orig/gcc/vec.h	2007-03-22 17:24:41.000000000 -0700
+++ S-vn-gtsmall/gcc/vec.h	2007-03-22 17:25:01.000000000 -0700
@@ -417,7 +417,6 @@
 #define VEC_lower_bound(T,V,O,LT)    \
        (VEC_OP(T,base,lower_bound)(VEC_BASE(V),O,LT VEC_CHECK_INFO))
 
-#if !IN_GENGTYPE
 /* Reallocate an array of elements with prefix.  */
 extern void *vec_gc_p_reserve (void *, int MEM_STAT_DECL);
 extern void *vec_gc_p_reserve_exact (void *, int MEM_STAT_DECL);
@@ -451,14 +450,12 @@
 #define VEC_ASSERT(EXPR,OP,T,A) (void)(EXPR)
 #endif
 
+/* Note: gengtype has hardwired knowledge of the expansions of the
+   VEC, DEF_VEC_*, and DEF_VEC_ALLOC_* macros.  If you change the
+   expansions of these macros you may need to change gengtype too.  */
+
 #define VEC(T,A) VEC_##T##_##A
 #define VEC_OP(T,A,OP) VEC_##T##_##A##_##OP
-#else  /* IN_GENGTYPE */
-#define VEC(T,A) VEC_ T _ A
-#define VEC_STRINGIFY(X) VEC_STRINGIFY_(X)
-#define VEC_STRINGIFY_(X) #X
-#undef GTY
-#endif /* IN_GENGTYPE */
 
 /* Base of vector type, not user visible.  */     
 #define VEC_T(T,B)							  \
@@ -488,10 +485,6 @@
 #define VEC_BASE(P)  ((P) ? &(P)->base : 0)
 
 /* Vector of integer-like object.  */
-#if IN_GENGTYPE
-{"DEF_VEC_I", VEC_STRINGIFY (VEC_T(#0,#1)) ";", "none"},
-{"DEF_VEC_ALLOC_I", VEC_STRINGIFY (VEC_TA (#0,#1,#2,#3)) ";", NULL},
-#else
 #define DEF_VEC_I(T)							  \
 static inline void VEC_OP (T,must_be,integral_type) (void) 		  \
 {									  \
@@ -506,13 +499,8 @@
 VEC_TA_GTY(T,base,A,);							  \
 DEF_VEC_ALLOC_FUNC_I(T,A)						  \
 struct vec_swallow_trailing_semi
-#endif
 
 /* Vector of pointer to object.  */
-#if IN_GENGTYPE
-{"DEF_VEC_P", VEC_STRINGIFY (VEC_T_GTY(#0,#1)) ";", "none"},
-{"DEF_VEC_ALLOC_P", VEC_STRINGIFY (VEC_TA_GTY (#0,#1,#2,#3)) ";", NULL},
-#else
 #define DEF_VEC_P(T) 							  \
 static inline void VEC_OP (T,must_be,pointer_type) (void) 		  \
 {									  \
@@ -527,7 +515,6 @@
 VEC_TA_GTY(T,base,A,);							  \
 DEF_VEC_ALLOC_FUNC_P(T,A)						  \
 struct vec_swallow_trailing_semi
-#endif
 
 #define DEF_VEC_FUNC_P(T)						  \
 static inline unsigned VEC_OP (T,base,length) (const VEC(T,base) *vec_)   \
@@ -809,10 +796,6 @@
 }
 
 /* Vector of object.  */
-#if IN_GENGTYPE
-{"DEF_VEC_O", VEC_STRINGIFY (VEC_T_GTY(#0,#1)) ";", "none"},
-{"DEF_VEC_ALLOC_O", VEC_STRINGIFY (VEC_TA_GTY(#0,#1,#2,#3)) ";", NULL},
-#else
 #define DEF_VEC_O(T)							  \
 VEC_T_GTY(T,base);							  \
 VEC_TA_GTY(T,base,none,);						  \
@@ -822,7 +805,6 @@
 VEC_TA_GTY(T,base,A,);							  \
 DEF_VEC_ALLOC_FUNC_O(T,A)						  \
 struct vec_swallow_trailing_semi
-#endif
 
 #define DEF_VEC_FUNC_O(T)						  \
 static inline unsigned VEC_OP (T,base,length) (const VEC(T,base) *vec_)	  \
Index: S-vn-gtsmall/gcc/Makefile.in
===================================================================
--- S-vn-gtsmall.orig/gcc/Makefile.in	2007-03-22 17:24:41.000000000 -0700
+++ S-vn-gtsmall/gcc/Makefile.in	2007-03-22 17:25:01.000000000 -0700
@@ -3136,11 +3136,11 @@
   $(SYSTEM_H) coretypes.h $(GTM_H) errors.h gensupport.h
 build/gengenrtl.o : gengenrtl.c $(BCONFIG_H) $(SYSTEM_H) rtl.def
 build/gengtype-lex.o : gengtype-lex.c gengtype.h gengtype-yacc.h	\
-  $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_H) vec.h
+  $(BCONFIG_H) $(SYSTEM_H)
 build/gengtype-yacc.o : gengtype-yacc.c gengtype.h $(BCONFIG_H)		\
-  $(SYSTEM_H) coretypes.h $(GTM_H)
-build/gengtype.o : gengtype.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h	\
-  $(GTM_H) gengtype.h gtyp-gen.h rtl.def insn-notes.def errors.h
+  $(SYSTEM_H)
+build/gengtype.o : gengtype.c $(BCONFIG_H) $(SYSTEM_H) gengtype.h 	\
+  gtyp-gen.h rtl.def insn-notes.def errors.h
 build/genmddeps.o: genmddeps.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h	\
   $(GTM_H) $(RTL_BASE_H) errors.h gensupport.h
 build/genmodes.o : genmodes.c $(BCONFIG_H) $(SYSTEM_H) errors.h		\
Index: S-vn-gtsmall/gcc/gengtype-yacc.y
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype-yacc.y	2007-03-22 17:24:55.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype-yacc.y	2007-03-22 17:25:01.000000000 -0700
@@ -39,6 +39,7 @@
 %token <t>ENT_STRUCT
 %token ENT_EXTERNSTATIC
 %token GTY_TOKEN
+%token VEC_TOKEN
 %token UNION
 %token STRUCT
 %token ENUM
@@ -160,6 +161,9 @@
          { $$ = $1; }
       | ID
          { $$ = resolve_typedef ($1, &lexer_line); }
+      | VEC_TOKEN '(' ID ',' ID ')'
+         { $$ = resolve_typedef (concat ("VEC_", $3, "_", $5, (char *)0),
+	      			 &lexer_line); }
       | type '*'
          { $$ = create_pointer ($1); }
       | STRUCT ID '{' struct_fields '}'
Subject: Simplify handling of scalar types

TYPE_SCALARs save their declared types as strings, but the only
thing this is used for is deciding whether to substitute TYPE_STRING
for an array or pointer type in adjust_field_type.  So replace it with
a boolean.  Also, rearrange data flow a little so that yylex passes
back a string rather than a type_p for the SCALAR terminal (after the
next patch, yylex will deal only in strings).

In case anyone is wondering, scalar_char and scalar_nonchar are fully
initialized at runtime rather than in their definitions because there is
no way in C90 to initialize any member of a union but the first.  We
wouldn't gain anything by it anyway - they can't be const because their
pointer_to fields may get filled out at some point.

	* gengtype.h (struct type): Replace 'sc' with boolean, scalar_is_char.
	(string_type): Don't declare.
	(do_scalar_typedef): Declare.
	(create_scalar_type): Update prototype.
	* gengtype.c (string_type): Make static.
	(scalar_nonchar, scalar_char): New.
	(do_scalar_typedef): Export.  Always use scalar_nonchar for the type.
	(resolve_typedef): Use scalar_nonchar for error recovery.
	(create_scalar_type): Remove name_len field.  Return scalar_char
	or scalar_nonchar as appropriate.
	(adjust_field_type): Look at scalar_is_char boolean to decide whether
	to use string_type.
	(throughout): Use scalar_nonchar instead of calling create_scalar_type,
	whenever possible.
	(main): Initialize scalar_char and scalar_nonchar before calling
	gen_rtx_next.
	* gengtype-lex.l: Adjust for removal of second argument to
	create_scalar_type.  Use yylval.s instead of yylval.t when
	returning SCALAR.
	* gengtype-yacc.y: Type of SCALAR is string.  Call
	create_scalar_type from type:SCALAR rule.  Adjust for removal of
	second argument to create_scalar_type.

Index: S-vn-gtsmall/gcc/gengtype.c
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype.c	2007-03-22 17:25:01.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype.c	2007-03-22 17:26:24.000000000 -0700
@@ -78,8 +78,18 @@
 
 /* The one and only TYPE_STRING.  */
 
-struct type string_type = {
-  TYPE_STRING, NULL, NULL, GC_USED, {0}
+static struct type string_type = {
+  TYPE_STRING, 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}
+};
+static struct type scalar_char = {
+  TYPE_SCALAR, 0, 0, GC_USED, {0}
 };
 
 /* Lists of various things.  */
@@ -89,7 +99,6 @@
 static type_p param_structs;
 static pair_p variables;
 
-static void do_scalar_typedef (const char *, struct fileloc *);
 static type_p find_param_structure
   (type_p t, type_p param[NUM_PARAM]);
 static type_p adjust_field_tree_exp (type_p t, options_p opt);
@@ -121,12 +130,14 @@
   typedefs = p;
 }
 
-/* Define S as a typename of a scalar.  */
+/* Define S as a typename of a scalar.  Cannot be used to define
+   typedefs of 'char'.  Note: is also used for pointer-to-function
+   typedefs (which are therefore not treated as pointers).  */
 
-static void
+void
 do_scalar_typedef (const char *s, struct fileloc *pos)
 {
-  do_typedef (s, create_scalar_type (s, strlen (s)), pos);
+  do_typedef (s, &scalar_nonchar, pos);
 }
 
 /* Return the type previously defined for S.  Use POS to report errors.  */
@@ -139,7 +150,7 @@
     if (strcmp (p->name, s) == 0)
       return p->type;
   error_at_line (pos, "unidentified type `%s'", s);
-  return create_scalar_type ("char", 4);
+  return &scalar_nonchar;  /* treat as "int" */
 }
 
 /* Create and return a new structure with tag NAME (or a union iff
@@ -269,12 +280,12 @@
 /* Return a scalar type with name NAME.  */
 
 type_p
-create_scalar_type (const char *name, size_t name_len)
+create_scalar_type (const char *name)
 {
-  type_p r = XCNEW (struct type);
-  r->kind = TYPE_SCALAR;
-  r->u.sc = (char *) xmemdup (name, name_len, name_len + 1);
-  return r;
+  if (!strcmp (name, "char") || !strcmp (name, "unsigned char"))
+    return &scalar_char;
+  else
+    return &scalar_nonchar;
 }
 
 /* Return a pointer to T.  */
@@ -499,7 +510,7 @@
   bitmap_tp = create_pointer (find_structure ("bitmap_element_def", 0));
   basic_block_tp = create_pointer (find_structure ("basic_block_def", 0));
   constant_tp = create_pointer (find_structure ("constant_descriptor_rtx", 0));
-  scalar_tp = create_scalar_type ("rtunion scalar", 14);
+  scalar_tp = &scalar_nonchar;  /* rtunion int */
 
   {
     pair_p note_flds = NULL;
@@ -796,13 +807,11 @@
   if (! length_p
       && pointer_p
       && t->u.p->kind == TYPE_SCALAR
-      && (strcmp (t->u.p->u.sc, "char") == 0
-	  || strcmp (t->u.p->u.sc, "unsigned char") == 0))
+      && t->u.p->u.scalar_is_char)
     return &string_type;
   if (t->kind == TYPE_ARRAY && t->u.a.p->kind == TYPE_POINTER
       && t->u.a.p->u.p->kind == TYPE_SCALAR
-      && (strcmp (t->u.a.p->u.p->u.sc, "char") == 0
-	  || strcmp (t->u.a.p->u.p->u.sc, "unsigned char") == 0))
+      && t->u.a.p->u.p->u.scalar_is_char)
     return create_array (&string_type, t->u.a.len);
 
   return t;
@@ -3015,7 +3024,7 @@
 
   if (is_scalar)
     {
-      t = create_scalar_type (typename, strlen (typename));
+      t = create_scalar_type (typename);
       o = 0;
     }
   else
@@ -3034,7 +3043,7 @@
   fields = f;
 
   f = XNEW (struct pair);
-  f->type = adjust_field_type (create_scalar_type ("unsigned", 8), 0);
+  f->type = adjust_field_type (create_scalar_type ("unsigned"), 0);
   f->name = "alloc";
   f->opt = 0;
   f->line = *pos;
@@ -3042,7 +3051,7 @@
   fields = f;
 
   f = XNEW (struct pair);
-  f->type = adjust_field_type (create_scalar_type ("unsigned", 8), 0);
+  f->type = adjust_field_type (create_scalar_type ("unsigned"), 0);
   f->name = "num";
   f->opt = 0;
   f->line = *pos;
@@ -3083,10 +3092,13 @@
   static struct fileloc pos = { __FILE__, __LINE__ };
   unsigned j;
 
-  gen_rtx_next ();
-
   srcdir_len = strlen (srcdir);
 
+  scalar_char.u.scalar_is_char = true;
+  scalar_nonchar.u.scalar_is_char = false;
+
+  gen_rtx_next ();
+
   do_scalar_typedef ("CUMULATIVE_ARGS", &pos);
   do_scalar_typedef ("REAL_VALUE_TYPE", &pos);
   do_scalar_typedef ("double_int", &pos);
@@ -3101,9 +3113,7 @@
 
   do_typedef ("PTR", create_pointer (resolve_typedef ("void", &pos)), &pos);
 
-  do_typedef ("HARD_REG_SET", create_array (
-	      create_scalar_type ("unsigned long", strlen ("unsigned long")),
-	      "2"), &pos);
+  do_typedef ("HARD_REG_SET", create_array (&scalar_nonchar, "2"), &pos);
 
   for (i = 0; i < NUM_GT_FILES; i++)
     {
Index: S-vn-gtsmall/gcc/gengtype.h
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype.h	2007-03-22 17:25:01.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype.h	2007-03-22 17:26:24.000000000 -0700
@@ -90,7 +90,7 @@
       lang_bitmap bitmap;
       type_p lang_struct;
     } s;
-    char *sc;
+    bool scalar_is_char;
     struct {
       type_p p;
       const char *len;
@@ -112,9 +112,6 @@
   || (x)->kind == TYPE_STRUCT 			\
   || (x)->kind == TYPE_LANG_STRUCT)
 
-/* The one and only TYPE_STRING.  */
-extern struct type string_type;
-
 /* Variables used to communicate between the lexer and the parser.  */
 extern int lexer_toplevel_done;
 extern struct fileloc lexer_line;
@@ -132,12 +129,13 @@
 
 /* Constructor routines for types.  */
 extern void do_typedef (const char *s, type_p t, struct fileloc *pos);
+extern void do_scalar_typedef (const char *s, struct fileloc *pos);
 extern type_p resolve_typedef (const char *s, struct fileloc *pos);
 extern type_p new_structure (const char *name, int isunion,
 			     struct fileloc *pos, pair_p fields,
 			     options_p o);
 extern type_p find_structure (const char *s, int isunion);
-extern type_p create_scalar_type (const char *name, size_t name_len);
+extern type_p create_scalar_type (const char *name);
 extern type_p create_pointer (type_p t);
 extern type_p create_array (type_p t, const char *len);
 extern options_p create_option (options_p, const char *name, const void *info);
Index: S-vn-gtsmall/gcc/gengtype-lex.l
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype-lex.l	2007-03-22 17:26:21.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype-lex.l	2007-03-22 17:26:24.000000000 -0700
@@ -95,7 +95,6 @@
 
   char *namestart;
   size_t namelen;
-  struct type *t;
   char *typestart;
   size_t typelen;
 
@@ -112,9 +111,10 @@
        ISSPACE (typestart[typelen-1]);
        typelen--)
     ;
+  typestart[typelen] = '\0';
 
-  t = create_scalar_type (typestart, typelen);
-  do_typedef ((const char *) xmemdup (namestart, namelen, namelen+1), t,
+  do_typedef ((const char *) xmemdup (namestart, namelen, namelen+1),
+  	      create_scalar_type (typestart),
 	      &lexer_line);
   update_lineno (yytext, yyleng);
 }
@@ -122,7 +122,6 @@
 [^[:alnum:]_]typedef{WS}{ID}{WS}{ID}{WS}"(" {
   char *namestart;
   size_t namelen;
-  struct type *t;
 
   for (namestart = yytext + yyleng - 2; ISSPACE (*namestart); namestart--)
     ;
@@ -130,16 +129,14 @@
     ;
   namestart -= namelen - 1;
 
-  t = create_scalar_type ("function type", sizeof ("function type")-1);
-  do_typedef ((const char *) xmemdup (namestart, namelen, namelen+1), t,
-	      &lexer_line);
+  do_scalar_typedef ((const char *) xmemdup (namestart, namelen, namelen+1),
+  		     &lexer_line);
   update_lineno (yytext, yyleng);
 }
 
 [^[:alnum:]_]typedef{WS}{ID}{WS}?"*"?{WS}?"("{WS}?"*"{WS}?{ID}{WS}?")"{WS}?"(" {
   char *namestart;
   size_t namelen;
-  struct type *t;
 
   for (namestart = yytext + yyleng - 2; !ISIDNUM (*namestart); namestart--)
     ;
@@ -147,9 +144,8 @@
     ;
   namestart -= namelen - 1;
 
-  t = create_scalar_type ("function type", sizeof ("function type")-1);
-  do_typedef ((const char *) xmemdup (namestart, namelen, namelen+1), t,
-	      &lexer_line);
+  do_scalar_typedef ((const char *) xmemdup (namestart, namelen, namelen+1),
+  		     &lexer_line);
   update_lineno (yytext, yyleng);
 }
 
@@ -270,7 +266,7 @@
   for (len = yyleng; ISSPACE (yytext[len-1]); len--)
     ;
 
-  yylval.t = create_scalar_type (yytext, len);
+  yylval.s = (const char *) xmemdup (yytext, len, len+1);
   update_lineno (yytext, yyleng);
   return SCALAR;
 }
Index: S-vn-gtsmall/gcc/gengtype-yacc.y
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype-yacc.y	2007-03-22 17:25:01.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype-yacc.y	2007-03-22 17:26:24.000000000 -0700
@@ -47,7 +47,7 @@
 %token NESTED_PTR
 %token <s>PARAM_IS
 %token NUM
-%token <t>SCALAR
+%token <s>SCALAR
 %token <s>ID
 %token <s>STRING
 %token <s>ARRAY
@@ -158,7 +158,7 @@
 	     ;
 
 type: SCALAR
-         { $$ = $1; }
+         { $$ = create_scalar_type ($1); }
       | ID
          { $$ = resolve_typedef ($1, &lexer_line); }
       | VEC_TOKEN '(' ID ',' ID ')'
@@ -175,9 +175,9 @@
       | UNION ID
          { $$ = find_structure ($2, 1); }
       | ENUM ID
-         { $$ = create_scalar_type ($2, strlen ($2)); }
+         { $$ = create_scalar_type ($2); }
       | ENUM ID '{' enum_items '}'
-         { $$ = create_scalar_type ($2, strlen ($2)); }
+         { $$ = create_scalar_type ($2); }
       ;
 
 enum_items: /* empty */
Subject: Simplify structure creation

By introducing two more pseudo-terminals, we can eliminate the need
for gengtype-yacc.y to go poking around inside type structures, and
also get rid of the last place where gengtype-lex.l was producing
type structures instead of strings.  Furthermore this avoids extra
work - there's no need to call find_structure before new_structure.
Also introduce a wrapper function so gengtype-yacc.y doesn't need to
see struct nested_ptr_data either.  (All these types are still
visible; eliminating that is the next patch.)

	* gengtype-lex.l: Distinguish unions from structures in the
	token type.  Don't call find_structure; return the tag as a string.
	* gengtype-yacc.y: Add new token types ENT_TYPEDEF_UNION and ENT_UNION.
	Type of these, ENT_TYPEDEF_STRUCT, and ENT_STRUCT is string.
	Reorganize typedef_struct production accordingly.
	Use create_nested_ptr_option.
	* gengtype.c (create_nested_ptr_option): New function.
	* gengtype.h: Declare it.

Index: S-vn-gtsmall/gcc/gengtype-lex.l
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype-lex.l	2007-03-22 17:26:24.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype-lex.l	2007-03-22 17:27:20.000000000 -0700
@@ -171,12 +171,12 @@
   for (taglen = 1; ISIDNUM (tagstart[taglen]); taglen++)
     ;
 
-  yylval.t = find_structure ((const char *) xmemdup (tagstart, taglen,
-						     taglen + 1),
-			     union_p);
+  yylval.s = (const char *) xmemdup (tagstart, taglen, taglen + 1);
+
   BEGIN(in_struct);
   update_lineno (yytext, yyleng);
-  return typedef_p ? ENT_TYPEDEF_STRUCT : ENT_STRUCT;
+  return union_p ? (typedef_p ? ENT_TYPEDEF_UNION : ENT_UNION)
+                 : (typedef_p ? ENT_TYPEDEF_STRUCT : ENT_STRUCT);
 }
 
 [^[:alnum:]_](extern|static){WS}/"GTY" {
Index: S-vn-gtsmall/gcc/gengtype-yacc.y
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype-yacc.y	2007-03-22 17:26:24.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype-yacc.y	2007-03-22 17:27:20.000000000 -0700
@@ -35,8 +35,10 @@
   const char *s;
 }
 
-%token <t>ENT_TYPEDEF_STRUCT
-%token <t>ENT_STRUCT
+%token <s>ENT_TYPEDEF_STRUCT
+%token <s>ENT_STRUCT
+%token <s>ENT_TYPEDEF_UNION
+%token <s>ENT_UNION
 %token ENT_EXTERNSTATIC
 %token GTY_TOKEN
 %token VEC_TOKEN
@@ -68,21 +70,30 @@
 
 typedef_struct: ENT_TYPEDEF_STRUCT options '{' struct_fields '}' ID
 		   {
-		     new_structure ($1->u.s.tag, UNION_P ($1), &lexer_line,
-				    $4, $2);
-		     do_typedef ($6, $1, &lexer_line);
+		     type_p t = new_structure ($1, false, &lexer_line, $4, $2);
+		     do_typedef ($6, t, &lexer_line);
 		     lexer_toplevel_done = 1;
 		   }
-		 ';'
-		   {}
+		  ';'
+		| ENT_TYPEDEF_UNION options '{' struct_fields '}' ID
+		   {
+		     type_p t = new_structure ($1, true, &lexer_line, $4, $2);
+		     do_typedef ($6, t, &lexer_line);
+		     lexer_toplevel_done = 1;
+		   }
+		  ';'
 		| ENT_STRUCT options '{' struct_fields '}'
 		   {
-		     new_structure ($1->u.s.tag, UNION_P ($1), &lexer_line,
-				    $4, $2);
+		     new_structure ($1, false, &lexer_line, $4, $2);
 		     lexer_toplevel_done = 1;
 		   }
-		 ';'
-		   {}
+		  ';'
+		| ENT_UNION options '{' struct_fields '}'
+		   {
+		     new_structure ($1, true, &lexer_line, $4, $2);
+		     lexer_toplevel_done = 1;
+		   }
+		  ';'
 		;
 
 externstatic: ENT_EXTERNSTATIC options lasttype ID semiequal
@@ -210,15 +221,7 @@
 	| type_option '(' type ')'
 	    { $$ = create_option (NULL, $1, adjust_field_type ($3, NULL)); }
 	| NESTED_PTR '(' type ',' stringseq ',' stringseq ')'
-	    {
-	      struct nested_ptr_data d;
-
-	      d.type = adjust_field_type ($3, NULL);
-	      d.convert_to = $5;
-	      d.convert_from = $7;
-	      $$ = create_option (NULL, "nested_ptr",
-				  xmemdup (&d, sizeof (d), sizeof (d)));
-	    }
+	    { $$ = create_nested_ptr_option ($3, $5, $7); }
 	;
 
 optionseq: option
Index: S-vn-gtsmall/gcc/gengtype.c
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype.c	2007-03-22 17:26:24.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype.c	2007-03-22 17:27:20.000000000 -0700
@@ -330,6 +330,18 @@
   return o;
 }
 
+/* Return an options structure for a "nested_ptr" option.  */
+options_p
+create_nested_ptr_option (type_p t, const char *to, const char *from)
+{
+  struct nested_ptr_data *d = XNEW (struct nested_ptr_data);
+
+  d->type = adjust_field_type (t, 0);
+  d->convert_to = to;
+  d->convert_from = from;
+  return create_option (NULL, "nested_ptr", d);
+}
+
 /* Add a variable named S of type T with options O defined at POS,
    to `variables'.  */
 
Index: S-vn-gtsmall/gcc/gengtype.h
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype.h	2007-03-22 17:26:24.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype.h	2007-03-22 17:27:20.000000000 -0700
@@ -139,6 +139,8 @@
 extern type_p create_pointer (type_p t);
 extern type_p create_array (type_p t, const char *len);
 extern options_p create_option (options_p, const char *name, const void *info);
+extern options_p create_nested_ptr_option (type_p t, const char *from,
+					   const char *to);
 extern type_p adjust_field_type (type_p, options_p);
 extern void note_variable (const char *s, type_p t, options_p o,
 			   struct fileloc *pos);
Subject: Narrow inter-file interfaces

We can now make all of the types used in gengtype.c's interfaces opaque.
This requires some slight reorganization to some of the rules in
gengtype-yacc.y so that they use the first argument to create_field_at
and create_option rather than chaining fields and options by hand.  The
grammar for GTY((...)) options is slightly wrong, but I don't think it
matters since we will shortly eliminate gengtype-yacc.y altogether (and
its replacement gets the grammar right).

	* gengtype.h: Remove all type definitions to gengtype.c; leave
	only definitions of options_p, type_p, and pair_p as opaque
	pointers.  Update prototypes.

	* gengtype.c: Many type definitions moved here from gengtype.h.
	Consolidate type definitions at the top of the file.
	(xvasprintf): Delete.
	(xasprintf): Make static.
	(create_nested_pointer_option): Add 'next' parameter.
	(create_field_all, create_field_at): New functions.
	(create_field): Now a thin wrapper around create_field_all.
	(create_optional_field): Rename create_optional_field_ and add
	line argument.  Original name is now a macro which supplies
	__LINE__.
	(oprintf): Use vsnprintf directly.
	(close_output_files): Use fatal rather than perror/exit.
	(note_def_vec, note_def_vec_alloc): Use create_field_at.
	(main): Set progname.  Don't use exit.
	* gengtype-yacc.y (struct_fields): Use create_field_at.
	(option, optionseqopt): Delete.
	(optionseq): Consolidate productions from option here so we
	can use the first argument to create_option.

Index: S-vn-gtsmall/gcc/gengtype.c
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype.c	2007-03-22 17:27:20.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype.c	2007-03-22 17:27:24.000000000 -0700
@@ -22,9 +22,153 @@
 #include "bconfig.h"
 #include "system.h"
 #include "gengtype.h"
-#include "gtyp-gen.h"
 #include "errors.h"	/* for fatal */
 
+/* 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
+};
+
+typedef unsigned lang_bitmap;
+
+/* 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,
+    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)
+
+/* Structure representing an output file.  */
+struct outf
+{
+  struct outf *next;
+  const char *name;
+  size_t buflength;
+  size_t bufused;
+  char *buf;
+};
+typedef struct outf * outf_p;
+
+/* An output file, suitable for definitions, that can see declarations
+   made in INPUT_FILE and is linked into every language that uses
+   INPUT_FILE.  */
+extern outf_p get_output_file_with_visibility
+   (const char *input_file);
+const char *get_output_file_name (const char *);
+
+#include "gtyp-gen.h"
+
+/* A bitmap that specifies which of BASE_FILES should be used to
+   output a definition that is different for each language and must be
+   defined once in each language that uses INPUT_FILE.  */
+static lang_bitmap get_base_file_bitmap (const char *input_file);
+
+/* Print, like fprintf, to O.  */
+static void oprintf (outf_p o, const char *S, ...)
+     ATTRIBUTE_PRINTF_2;
+
+/* The list of output files.  */
+static outf_p output_files;
+
+/* The output header file that is included into pretty much every
+   source file.  */
+static outf_p header_file;
+
+/* Number of files specified in gtfiles.  */
+#define NUM_GT_FILES (ARRAY_SIZE (all_files) - 1)
+
+/* Number of files in the language files array.  */
+#define NUM_LANG_FILES (ARRAY_SIZE (lang_files) - 1)
+
+/* Length of srcdir name.  */
+static int srcdir_len = 0;
+
+/* A list of output files suitable for definitions.  There is one
+   BASE_FILES entry for each language.  */
+#define NUM_BASE_FILES (ARRAY_SIZE (lang_dir_names) - 1)
+static outf_p base_files[NUM_BASE_FILES];
+
+static outf_p create_file (const char *, const char *);
+static const char * get_file_basename (const char *);
+
+
 /* Nonzero iff an error has occurred.  */
 static int hit_error = 0;
 
@@ -50,29 +194,20 @@
   va_end (ap);
 }
 
-/* vasprintf, but produces fatal message on out-of-memory.  */
-int
-xvasprintf (char **result, const char *format, va_list args)
-{
-  int ret = vasprintf (result, format, args);
-  if (*result == NULL || ret < 0)
-    {
-      fputs ("gengtype: out of memory", stderr);
-      xexit (1);
-    }
-  return ret;
-}
-
-/* Wrapper for xvasprintf.  */
-char *
+/* asprintf, but produces fatal message on out-of-memory.  */
+static char * ATTRIBUTE_PRINTF_1
 xasprintf (const char *format, ...)
 {
+  int n;
   char *result;
   va_list ap;
 
   va_start (ap, format);
-  xvasprintf (&result, format, ap);
+  n = vasprintf (&result, format, ap);
+  if (result == NULL || n < 0)
+    fatal ("out of memory");
   va_end (ap);
+
   return result;
 }
 
@@ -332,14 +467,15 @@
 
 /* Return an options structure for a "nested_ptr" option.  */
 options_p
-create_nested_ptr_option (type_p t, const char *to, const char *from)
+create_nested_ptr_option (options_p next, type_p t,
+			  const char *to, const char *from)
 {
   struct nested_ptr_data *d = XNEW (struct nested_ptr_data);
 
   d->type = adjust_field_type (t, 0);
   d->convert_to = to;
   d->convert_from = from;
-  return create_option (NULL, "nested_ptr", d);
+  return create_option (next, "nested_ptr", d);
 }
 
 /* Add a variable named S of type T with options O defined at POS,
@@ -358,11 +494,10 @@
   variables = n;
 }
 
-/* Create a fake field with the given type and name.  NEXT is the next
-   field in the chain.  */
-
+/* Most-general structure field creator.  */
 static pair_p
-create_field (pair_p next, type_p type, const char *name)
+create_field_all (pair_p next, type_p type, const char *name, options_p opt,
+		  const char *file, int line)
 {
   pair_p field;
 
@@ -370,21 +505,37 @@
   field->next = next;
   field->type = type;
   field->name = name;
-  field->opt = NULL;
-  field->line.file = __FILE__;
-  field->line.line = __LINE__;
+  field->opt = opt;
+  field->line.file = file;
+  field->line.line = line;
   return field;
 }
 
+/* Create a field that came from the source code we are scanning,
+   i.e. we have a 'struct fileloc', and possibly options; also,
+   adjust_field_type should be called.  */
+pair_p
+create_field_at (pair_p next, type_p type, const char *name, options_p opt,
+		 struct fileloc *pos)
+{
+  return create_field_all (next, adjust_field_type (type, opt),
+			   name, opt, pos->file, 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, __FILE__, __LINE__)
+
 /* Like create_field, but the field is only valid when condition COND
    is true.  */
 
 static pair_p
-create_optional_field (pair_p next, type_p type, const char *name,
-		       const char *cond)
+create_optional_field_ (pair_p next, type_p type, const char *name,
+			const char *cond, int line)
 {
   static int id = 1;
-  pair_p union_fields, field;
+  pair_p union_fields;
   type_p union_type;
 
   /* Create a fake union type with a single nameless field of type TYPE.
@@ -398,10 +549,12 @@
 
   /* 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.  */
-  field = create_field (next, union_type, name);
-  field->opt = create_option (field->opt, "desc", cond);
-  return field;
+  return create_field_all (next, union_type, name,
+			   create_option (0, "desc", cond),
+			   __FILE__, line);
 }
+#define create_optional_field(next,type,name,cond)	\
+       create_optional_field_(next,type,name,cond,__LINE__)
 
 /* We don't care how long a CONST_DOUBLE is.  */
 #define CONST_DOUBLE_FORMAT "ww"
@@ -953,27 +1106,7 @@
    (but some output files have many input files), and there is one .h file
    for the whole build.  */
 
-/* The list of output files.  */
-static outf_p output_files;
-
-/* The output header file that is included into pretty much every
-   source file.  */
-static outf_p header_file;
-
-/* Number of files specified in gtfiles.  */
-#define NUM_GT_FILES (ARRAY_SIZE (all_files) - 1)
-
-/* Number of files in the language files array.  */
-#define NUM_LANG_FILES (ARRAY_SIZE (lang_files) - 1)
-
-/* Length of srcdir name.  */
-static int srcdir_len = 0;
-
-#define NUM_BASE_FILES (ARRAY_SIZE (lang_dir_names) - 1)
-outf_p base_files[NUM_BASE_FILES];
-
-static outf_p create_file (const char *, const char *);
-static const char * get_file_basename (const char *);
+/* Output file handling.  */
 
 /* Create and return an outf_p for a new file for NAME, to be called
    ONAME.  */
@@ -1021,15 +1154,20 @@
 void
 oprintf (outf_p o, const char *format, ...)
 {
-  char *s;
   size_t slength;
-  va_list ap;
 
-  va_start (ap, format);
-  slength = xvasprintf (&s, format, ap);
+  /* Try first with the assumption that there is enough space.  */
+  {
+    va_list ap;
+    va_start (ap, format);
+    slength = vsnprintf (o->buf + o->bufused, o->buflength - o->bufused,
+			 format, ap);
+    va_end (ap);
+  }
 
-  if (o->bufused + slength > o->buflength)
+  if (o->bufused + slength >= o->buflength)
     {
+      /* There wasn't enough space.  */
       size_t new_len = o->buflength;
       if (new_len == 0)
 	new_len = 1024;
@@ -1038,11 +1176,21 @@
       } while (o->bufused + slength >= new_len);
       o->buf = XRESIZEVEC (char, o->buf, new_len);
       o->buflength = new_len;
+
+      /* We now know that there is enough space. */
+      {
+	size_t slen2;
+	va_list ap;
+	va_start (ap, format);
+	slen2 = vsnprintf (o->buf + o->bufused, o->buflength - o->bufused,
+			   format, ap);
+	va_end (ap);
+
+	gcc_assert (slen2 == slength);
+	gcc_assert (o->bufused + slen2 < o->buflength);
+      }
     }
-  memcpy (o->buf + o->bufused, s, slength);
   o->bufused += slength;
-  free (s);
-  va_end (ap);
 }
 
 /* Open the global header file and the language-specific header files.  */
@@ -1298,20 +1446,11 @@
 
       newfile = fopen (of->name, "w");
       if (newfile == NULL)
-	{
-	  perror ("opening output file");
-	  exit (1);
-	}
+	fatal ("opening output file %s: %s", of->name, strerror (errno));
       if (fwrite (of->buf, 1, of->bufused, newfile) != of->bufused)
-	{
-	  perror ("writing output file");
-	  exit (1);
-	}
+	fatal ("writing output file %s: %s", of->name, strerror (errno));
       if (fclose (newfile) != 0)
-	{
-	  perror ("closing output file");
-	  exit (1);
-	}
+	fatal ("closing output file %s: %s", of->name, strerror (errno));
     }
 }
 
@@ -3029,9 +3168,10 @@
 void
 note_def_vec (const char *typename, bool is_scalar, struct fileloc *pos)
 {
-  pair_p f, fields;
+  pair_p fields;
   type_p t;
   options_p o;
+  type_p len_ty = create_scalar_type ("unsigned");
   const char *name = concat ("VEC_", typename, "_base", (char *)0);
 
   if (is_scalar)
@@ -3046,29 +3186,9 @@
     }
 
   /* We assemble the field list in reverse order.  */
-  f = XNEW (struct pair);
-  f->type = adjust_field_type (create_array (t, "1"), o);
-  f->name = "vec";
-  f->opt = o;
-  f->line = *pos;
-  f->next = 0;
-  fields = f;
-
-  f = XNEW (struct pair);
-  f->type = adjust_field_type (create_scalar_type ("unsigned"), 0);
-  f->name = "alloc";
-  f->opt = 0;
-  f->line = *pos;
-  f->next = fields;
-  fields = f;
-
-  f = XNEW (struct pair);
-  f->type = adjust_field_type (create_scalar_type ("unsigned"), 0);
-  f->name = "num";
-  f->opt = 0;
-  f->line = *pos;
-  f->next = fields;
-  fields = f;
+  fields = create_field_at (0, create_array (t, "1"), "vec", o, pos);
+  fields = create_field_at (fields, len_ty, "alloc", 0, pos);
+  fields = create_field_at (fields, len_ty, "num", 0, pos);
 
   do_typedef (name, new_structure (name, 0, pos, fields, 0), pos);
 }
@@ -3086,11 +3206,8 @@
   const char *astratname = concat ("VEC_", type, "_", astrat, (char *)0);
   const char *basename = concat ("VEC_", type, "_base", (char *)0);
 
-  pair_p field = XNEW (struct pair);
-  field->name = "base";
-  field->type = adjust_field_type (resolve_typedef (basename, pos), 0);
-  field->line = *pos;
-  field->next = 0;
+  pair_p field = create_field_at (0, resolve_typedef (basename, pos),
+				  "base", 0, pos);
 
   do_typedef (astratname, new_structure (astratname, 0, pos, field, 0), pos);
 }
@@ -3109,6 +3226,9 @@
   scalar_char.u.scalar_is_char = true;
   scalar_nonchar.u.scalar_is_char = false;
 
+  /* fatal uses this */
+  progname = "gengtype";
+
   gen_rtx_next ();
 
   do_scalar_typedef ("CUMULATIVE_ARGS", &pos);
@@ -3150,7 +3270,7 @@
     }
 
   if (hit_error != 0)
-    exit (1);
+    return 1;
 
   set_gc_used (variables);
 
Index: S-vn-gtsmall/gcc/gengtype.h
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype.h	2007-03-22 17:27:20.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype.h	2007-03-22 17:27:24.000000000 -0700
@@ -18,6 +18,9 @@
 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 02110-1301, USA.  */
 
+#ifndef GCC_GENGTYPE_H
+#define GCC_GENGTYPE_H
+
 /* A file position, mostly for error messages.  
    The FILE element may be compared using pointer equality.  */
 struct fileloc {
@@ -25,92 +28,10 @@
   int line;
 };
 
-/* 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
-};
-
+/* Data types handed around within, but opaque to, the lexer and parser.  */
 typedef struct pair *pair_p;
 typedef struct type *type_p;
-typedef unsigned lang_bitmap;
-
-/* Option data for the 'nested_ptr' option.  */
-struct nested_ptr_data {
-  type_p type;
-  const char *convert_to;
-  const char *convert_from;
-};    
-
-/* A way to pass data through to the output end.  */
-typedef struct options {
-  struct options *next;
-  const char *name;
-  const char *info;
-} *options_p;
-
-/* 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,
-    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)
+typedef struct options *options_p;
 
 /* Variables used to communicate between the lexer and the parser.  */
 extern int lexer_toplevel_done;
@@ -120,13 +41,6 @@
 extern void error_at_line 
   (struct fileloc *pos, const char *msg, ...) ATTRIBUTE_PRINTF_2;
 
-/* Combines xmalloc() and vasprintf().  */
-extern int xvasprintf (char **, const char *, va_list)
-     ATTRIBUTE_PRINTF (2, 0);
-/* Like the above, but more convenient for quick coding.  */
-extern char * xasprintf (const char *, ...)
-     ATTRIBUTE_PRINTF_1;
-
 /* Constructor routines for types.  */
 extern void do_typedef (const char *s, type_p t, struct fileloc *pos);
 extern void do_scalar_typedef (const char *s, struct fileloc *pos);
@@ -139,8 +53,10 @@
 extern type_p create_pointer (type_p t);
 extern type_p create_array (type_p t, const char *len);
 extern options_p create_option (options_p, const char *name, const void *info);
-extern options_p create_nested_ptr_option (type_p t, const char *from,
-					   const char *to);
+extern options_p create_nested_ptr_option (options_p, type_p t,
+					   const char *from, const char *to);
+extern pair_p create_field_at (pair_p next, type_p type, const char *name,
+			       options_p opt, struct fileloc *pos);
 extern type_p adjust_field_type (type_p, options_p);
 extern void note_variable (const char *s, type_p t, options_p o,
 			   struct fileloc *pos);
@@ -155,36 +71,4 @@
 extern int yyparse (void);
 extern void parse_file (const char *name);
 
-/* Output file handling.  */
-
-/* Structure representing an output file.  */
-struct outf 
-{
-  struct outf *next;
-  const char *name;
-  size_t buflength;
-  size_t bufused;
-  char *buf;
-};
-
-typedef struct outf * outf_p;
-
-/* An output file, suitable for definitions, that can see declarations
-   made in INPUT_FILE and is linked into every language that uses
-   INPUT_FILE.  */
-extern outf_p get_output_file_with_visibility 
-   (const char *input_file);
-const char *get_output_file_name (const char *);
-
-/* A list of output files suitable for definitions.  There is one
-   BASE_FILES entry for each language.  */
-extern outf_p base_files[];
-
-/* A bitmap that specifies which of BASE_FILES should be used to
-   output a definition that is different for each language and must be
-   defined once in each language that uses INPUT_FILE.  */
-extern lang_bitmap get_base_file_bitmap (const char *input_file);
-
-/* Print, like fprintf, to O.  */
-extern void oprintf (outf_p o, const char *S, ...)
-     ATTRIBUTE_PRINTF_2;
+#endif
Index: S-vn-gtsmall/gcc/gengtype-yacc.y
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype-yacc.y	2007-03-22 17:27:20.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype-yacc.y	2007-03-22 17:27:24.000000000 -0700
@@ -57,7 +57,7 @@
 
 %type <p> struct_fields
 %type <t> type lasttype
-%type <o> optionsopt options option optionseq optionseqopt
+%type <o> optionsopt options optionseq
 %type <s> type_option stringseq
 
 %%
@@ -128,33 +128,17 @@
 struct_fields: { $$ = NULL; }
 	       | type optionsopt ID bitfieldopt ';' struct_fields
 	          {
-	            pair_p p = XNEW (struct pair);
-		    p->type = adjust_field_type ($1, $2);
-		    p->opt = $2;
-		    p->name = $3;
-		    p->next = $6;
-		    p->line = lexer_line;
-		    $$ = p;
+		    $$ = create_field_at ($6, $1, $3, $2, &lexer_line);
 		  }
 	       | type optionsopt ID ARRAY ';' struct_fields
 	          {
-	            pair_p p = XNEW (struct pair);
-		    p->type = adjust_field_type (create_array ($1, $4), $2);
-		    p->opt = $2;
-		    p->name = $3;
-		    p->next = $6;
-		    p->line = lexer_line;
-		    $$ = p;
+		    $$ = create_field_at ($6, create_array ($1, $4),
+		    			  $3, $2, &lexer_line);
 		  }
 	       | type optionsopt ID ARRAY ARRAY ';' struct_fields
 	          {
-	            pair_p p = XNEW (struct pair);
-		    p->type = create_array (create_array ($1, $5), $4);
-		    p->opt = $2;
-		    p->name = $3;
-		    p->next = $7;
-		    p->line = lexer_line;
-		    $$ = p;
+		    type_p arr = create_array (create_array ($1, $5), $4);
+		    $$ = create_field_at ($7, arr, $3, $2, &lexer_line);
 		  }
 	       | type ':' bitfieldlen ';' struct_fields
 		  { $$ = $5; }
@@ -204,7 +188,7 @@
 	    | options { $$ = $1; }
 	    ;
 
-options: GTY_TOKEN '(' '(' optionseqopt ')' ')'
+options: GTY_TOKEN '(' '(' optionseq ')' ')'
 	   { $$ = $4; }
 	 ;
 
@@ -214,31 +198,19 @@
 	        { $$ = $1; }
 	      ;
 
-option:   ID
-	    { $$ = create_option (NULL, $1, (void *)""); }
-        | ID '(' stringseq ')'
-            { $$ = create_option (NULL, $1, (void *)$3); }
-	| type_option '(' type ')'
-	    { $$ = create_option (NULL, $1, adjust_field_type ($3, NULL)); }
-	| NESTED_PTR '(' type ',' stringseq ',' stringseq ')'
-	    { $$ = create_nested_ptr_option ($3, $5, $7); }
-	;
-
-optionseq: option
-	      {
-	        $1->next = NULL;
-		$$ = $1;
-	      }
-	    | optionseq ',' option
-	      {
-	        $3->next = $1;
-		$$ = $3;
-	      }
-	    ;
-
-optionseqopt: { $$ = NULL; }
-	      | optionseq { $$ = $1; }
-	      ;
+optionseq: { $$ = NULL; }
+	| optionseq commaopt ID
+	   { $$ = create_option ($1, $3, (void *)""); }
+	| optionseq commaopt ID '(' stringseq ')'
+	   { $$ = create_option ($1, $3, (void *)$5); }
+	| optionseq commaopt type_option '(' type ')'
+	   { $$ = create_option ($1, $3, adjust_field_type ($5, 0)); }
+	| optionseq commaopt NESTED_PTR '(' type ',' stringseq ',' stringseq ')'
+	   { $$ = create_nested_ptr_option ($1, $5, $7, $9); }
+
+commaopt: /* nothing */
+	  | ','
+	  ;
 
 stringseq: STRING
 	     { $$ = $1; }
Subject: Don't compile in the list of input files

Now things get a little more interesting.  This patch causes gengtype
to read its list of input files from a file specified on the command
line, rather than having that list compiled into the program.  I
defined a sensible input-file-list syntax rather than preserve the set
of arrays that used to appear in gtyp-gen.h, therefore the gengtype
changes are more extensive than it might seem they ought to be.

This change had the interesting consequence of revealing a whole bunch
of C-(family-)specific files that had somehow gotten into the main
GTFILES list (and tree-profile.c was in there twice for some reason).
Also, there was a completely unnecessary special case for C in
get_file_basename that assumed C was always the first entry in
lang_dir_names; that is no longer true.

Unlike all preceding patches in this series, this one does cause
changes to gengtype's output.  I have manually inspected them and
verified that they are all just harmless changes to the order in which
various things are emitted; I have also tested this patch with a full
bootstrap (all languages including ada and treelang) instead of
stopping after confirming that there was no change to gengtype's
output.

There is more that could be done to clean up gengtype's input file
handling, but this patch is already plenty long.

	* gengtype.c: Don't include gtyp-gen.h.
	(srcdir): Declare here.
	(base_files, lang_dir_names): Allocate dynamically.
	(gt_files, num_gt_files, num_lang_dirs): New globals.
	(measure_input_list, read_input_line, read_input_list)
	(set_lang_bitmap): New functions.
	(get_base_file_bitmap): Rename get_lang_bitmap and drastically
	simplify, relying on read_input_list to set up the bitmaps.
	(main): Arguments are no longer unused.  Check for correct number
	of command line arguments, set srcdir and srcdir_len, then call
	read_input_list, before doing anything else.  No need to worry
	about duplicates in main loop.
	* configure.ac: Simplify the calculation of all_gtfiles.
	Put language tags in there.  Don't set or substitute
	all_gtfiles_files_langs or all_gtfiles_files_frags.
	* Makefile.in: Revamp the way gengtype is invoked, now that it
	takes a file on its command line with a much simpler format.
	Remove or replace with gtyp-input.list all references to gtyp-gen.h.
	(GTFILES): Remove duplicates and C source files.
	* c-config-lang.in, cp/config-lang.in, objc/config-lang.in
	* objcp/config-lang.in: Add c-pragma.h to gtfiles.

Index: S-vn-gtsmall/gcc/Makefile.in
===================================================================
--- S-vn-gtsmall.orig/gcc/Makefile.in	2007-03-22 17:25:01.000000000 -0700
+++ S-vn-gtsmall/gcc/Makefile.in	2007-03-22 17:27:27.000000000 -0700
@@ -1187,7 +1187,7 @@
  insn-attr.h insn-attrtab.c insn-opinit.c insn-preds.c insn-constants.h \
  tm-preds.h tm-constrs.h \
  tree-check.h min-insn-modes.c insn-modes.c insn-modes.h \
- genrtl.c genrtl.h gt-*.h gtype-*.h gtype-desc.c gtyp-gen.h \
+ genrtl.c genrtl.h gt-*.h gtype-*.h gtype-desc.c gtyp-input.list \
  xgcc$(exeext) cpp$(exeext) cc1$(exeext) cc1*-dummy$(exeext) $(EXTRA_PASSES) \
  $(EXTRA_PARTS) $(EXTRA_PROGRAMS) gcc-cross$(exeext) \
  protoize$(exeext) unprotoize$(exeext) \
@@ -2986,11 +2986,11 @@
   $(srcdir)/real.h $(srcdir)/varray.h $(srcdir)/insn-addr.h $(srcdir)/hwint.h \
   $(srcdir)/ipa-reference.h $(srcdir)/output.h \
   $(srcdir)/cselib.h $(srcdir)/basic-block.h  $(srcdir)/cgraph.h \
-  $(srcdir)/c-common.h $(srcdir)/c-tree.h $(srcdir)/reload.h \
+  $(srcdir)/reload.h \
   $(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c $(srcdir)/cgraph.c \
   $(srcdir)/ipa-prop.c $(srcdir)/ipa-cp.c $(srcdir)/ipa-inline.c \
   $(srcdir)/dbxout.c $(srcdir)/dwarf2out.c $(srcdir)/dwarf2asm.c \
-  $(srcdir)/dojump.c $(srcdir)/tree-profile.c \
+  $(srcdir)/dojump.c \
   $(srcdir)/emit-rtl.c $(srcdir)/except.c $(srcdir)/explow.c $(srcdir)/expr.c \
   $(srcdir)/function.c $(srcdir)/except.h \
   $(srcdir)/gcse.c $(srcdir)/integrate.c $(srcdir)/lists.c $(srcdir)/optabs.c \
@@ -2999,7 +2999,6 @@
   $(srcdir)/sdbout.c $(srcdir)/stor-layout.c \
   $(srcdir)/stringpool.c $(srcdir)/tree.c $(srcdir)/varasm.c \
   $(srcdir)/tree-mudflap.c $(srcdir)/tree-flow.h \
-  $(srcdir)/c-objc-common.c $(srcdir)/c-common.c $(srcdir)/c-parser.c \
   $(srcdir)/tree-ssanames.c $(srcdir)/tree-eh.c $(srcdir)/tree-ssa-address.c \
   $(srcdir)/tree-phinodes.c $(srcdir)/tree-cfg.c \
   $(srcdir)/tree-dfa.c $(srcdir)/tree-ssa-propagate.c \
@@ -3009,69 +3008,38 @@
   $(srcdir)/tree-profile.c $(srcdir)/tree-nested.c \
   $(srcdir)/ipa-reference.c $(srcdir)/tree-ssa-structalias.h \
   $(srcdir)/tree-ssa-structalias.c \
-  $(srcdir)/c-pragma.h $(srcdir)/omp-low.c $(srcdir)/varpool.c \
-  $(srcdir)/targhooks.c $(out_file) $(srcdir)/passes.c\
+  $(srcdir)/omp-low.c $(srcdir)/varpool.c \
+  $(srcdir)/targhooks.c $(out_file) $(srcdir)/passes.c \
   @all_gtfiles@
 
-GTFILES_FILES_LANGS = @all_gtfiles_files_langs@
-GTFILES_FILES_FILES = @all_gtfiles_files_files@
-GTFILES_LANG_DIR_NAMES = @subdirs@
-GTFILES_SRCDIR = @srcdir@
-
-GTFILES_FILES_FILES_C = $(subst $(srcdir)/,, \
-	$(filter %.c, $(GTFILES_FILES_FILES)))
-GTFILES_FILES_FILES_H = $(addprefix gt-, \
-	$(subst /,-,$(GTFILES_FILES_FILES_C:.c=.h)))
-GTFILES_LANG_DIR_NAMES_H = $(foreach d,$(GTFILES_LANG_DIR_NAMES), gtype-$(d).h)
-ALL_GTFILES_H := $(sort $(GTFILES_FILES_FILES_H) $(GTFILES_LANG_DIR_NAMES_H))
-
-$(ALL_GTFILES_H) : s-gtype ; @true
-
-
-gt-cgraph.h gt-coverage.h gtype-desc.h gtype-desc.c gt-except.h \
-gt-function.h gt-integrate.h gt-tree.h gt-varasm.h \
-gt-emit-rtl.h gt-explow.h gt-stor-layout.h gt-regclass.h \
-gt-lists.h gt-alias.h gt-cselib.h gt-gcse.h \
-gt-expr.h gt-sdbout.h gt-optabs.h gt-bitmap.h gt-dojump.h \
-gt-dwarf2out.h gt-dwarf2asm.h \
-gt-dbxout.h \
-gtype-c.h gt-cfglayout.h \
-gt-tree-mudflap.h gt-tree-vect-generic.h \
-gt-tree-profile.h gt-tree-ssa-address.h \
-gt-tree-iterator.h gt-gimplify.h \
-gt-tree-phinodes.h gt-tree-nested.h \
-gt-tree-ssa-propagate.h gt-varpool.h \
-gt-tree-ssa-structalias.h gt-ipa-inline.h gt-passes.h \
-gt-stringpool.h gt-targhooks.h gt-omp-low.h : s-gtype ; @true
+GTFILES_H = $(subst /,-, $(subst $(srcdir)/,gt-, $(subst .c,.h, \
+		  $(filter %.c, $(GTFILES)))))
 
-define echo_quoted_to_gtyp
- echo "\"$(gtyp)\", " >> tmp-gtyp.h
+GTFILES_LANG_H = $(patsubst [%], gtype-%.h, $(filter [%], $(GTFILES)))
+ALL_GTFILES_H := $(sort $(GTFILES_H) $(GTFILES_LANG_H))
+
+# $(GTFILES) may be too long to put on a command line, so we have to
+# write it out to a file (taking care not to do that in a way that
+# overflows a command line!) and then have gengtype read the file in.
+# The extra blank line in this definition is crucial: it makes the
+# $(foreach ...) below expand to many lines instead of one.
+
+define echo_to_gi.list
+echo '$(gtyp)' >> tmp-gi.list
 
 endef
 
-gtyp-gen.h: s-gtyp-gen ; @true
-s-gtyp-gen: Makefile
-	echo "/* This file is machine generated.  Do not edit.  */" > tmp-gtyp.h
-	echo "static const char *const srcdir = "  >> tmp-gtyp.h
-	echo "\"$(GTFILES_SRCDIR)\"" >> tmp-gtyp.h
-	echo ";" >> tmp-gtyp.h
-	echo "static const char *const lang_files[] = {" >> tmp-gtyp.h
-	$(foreach gtyp,$(GTFILES_FILES_FILES),$(echo_quoted_to_gtyp))
-	echo "NULL};" >> tmp-gtyp.h
-	echo "static const char *const langs_for_lang_files[] = {" >> tmp-gtyp.h
-	$(foreach gtyp,$(GTFILES_FILES_LANGS),$(echo_quoted_to_gtyp))
-	echo "NULL};" >> tmp-gtyp.h
-	echo "static const char *const all_files[] = {" >> tmp-gtyp.h
-	$(foreach gtyp,$(GTFILES),$(echo_quoted_to_gtyp))
-	echo " NULL};" >> tmp-gtyp.h
-	echo "static const char *const lang_dir_names[] = { \"c\", " >> tmp-gtyp.h
-	$(foreach gtyp,$(GTFILES_LANG_DIR_NAMES),$(echo_quoted_to_gtyp))
-	echo "NULL};" >> tmp-gtyp.h
-	$(SHELL) $(srcdir)/../move-if-change tmp-gtyp.h gtyp-gen.h
-	$(STAMP) s-gtyp-gen
+$(ALL_GTFILES_H) gtype-desc.c gtype-desc.h : s-gtype ; @true
 
-s-gtype: build/gengtype$(build_exeext) $(GTFILES)
-	$(RUN_GEN) build/gengtype$(build_exeext)
+gtyp-input.list: s-gtyp-input ; @true
+s-gtyp-input: Makefile
+	$(foreach gtyp, $(GTFILES), $(echo_to_gi.list))
+	$(SHELL) $(srcdir)/../move-if-change tmp-gi.list gtyp-input.list
+	$(STAMP) s-gtyp-input
+
+s-gtype: build/gengtype$(build_exeext) $(filter-out [%], $(GTFILES)) \
+	 gtyp-input.list
+	$(RUN_GEN) build/gengtype$(build_exeext) $(srcdir) gtyp-input.list
 	$(STAMP) s-gtype
 
 #
@@ -3140,7 +3108,7 @@
 build/gengtype-yacc.o : gengtype-yacc.c gengtype.h $(BCONFIG_H)		\
   $(SYSTEM_H)
 build/gengtype.o : gengtype.c $(BCONFIG_H) $(SYSTEM_H) gengtype.h 	\
-  gtyp-gen.h rtl.def insn-notes.def errors.h
+  rtl.def insn-notes.def errors.h
 build/genmddeps.o: genmddeps.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h	\
   $(GTM_H) $(RTL_BASE_H) errors.h gensupport.h
 build/genmodes.o : genmodes.c $(BCONFIG_H) $(SYSTEM_H) errors.h		\
@@ -3759,8 +3727,8 @@
 	-rm -f gcc.vrs gcc.kys gcc.tps gcc.pgs gcc.fns
 # Delete core dumps.
 	-rm -f core */core
-# Delete file generated for gengtype.c
-	-rm -f gtyp-gen.h
+# Delete file generated for gengtype
+	-rm -f gtyp-input.list
 # Delete files generated by gengtype.c
 	-rm -f gtype-*
 	-rm -f gt-*
Index: S-vn-gtsmall/gcc/configure.ac
===================================================================
--- S-vn-gtsmall.orig/gcc/configure.ac	2007-03-22 17:24:41.000000000 -0700
+++ S-vn-gtsmall/gcc/configure.ac	2007-03-22 17:27:27.000000000 -0700
@@ -3501,11 +3501,8 @@
 all_lang_makefrags=
 # List of language subdirectory makefiles.  Deprecated.
 all_lang_makefiles=
-# Files for gengtype
+# Additional files for gengtype
 all_gtfiles="$target_gtfiles"
-# Files for gengtype with language
-all_gtfiles_files_langs=
-all_gtfiles_files_files=
 
 # These are the languages that are set in --enable-languages,
 # and are available in the GCC tree.
@@ -3582,24 +3579,13 @@
 	all_languages="$all_languages $language"
 	all_compilers="$all_compilers $compilers"
 	all_outputs="$all_outputs $outputs"
-	all_gtfiles="$all_gtfiles $gtfiles"
-	for f in $gtfiles
-	do
-		all_gtfiles_files_langs="$all_gtfiles_files_langs ${subdir} "
-		all_gtfiles_files_files="$all_gtfiles_files_files ${f} "
-	done
+	all_gtfiles="$all_gtfiles [[$subdir]] $gtfiles"
 done
 
 # Pick up gtfiles for c
 gtfiles=
-subdir="c"
 . ${srcdir}/c-config-lang.in
-all_gtfiles="$all_gtfiles $gtfiles"
-for f in $gtfiles
-do
-        all_gtfiles_files_langs="$all_gtfiles_files_langs ${subdir} "
-        all_gtfiles_files_files="$all_gtfiles_files_files ${f} "
-done
+all_gtfiles="$all_gtfiles [[c]] $gtfiles"
 
 check_languages=
 for language in $all_selected_languages
@@ -3731,8 +3717,6 @@
 AC_SUBST(srcdir)
 AC_SUBST(all_compilers)
 AC_SUBST(all_gtfiles)
-AC_SUBST(all_gtfiles_files_langs)
-AC_SUBST(all_gtfiles_files_files)
 AC_SUBST(all_lang_makefrags)
 AC_SUBST(all_lang_makefiles)
 AC_SUBST(all_languages)
Index: S-vn-gtsmall/gcc/c-config-lang.in
===================================================================
--- S-vn-gtsmall.orig/gcc/c-config-lang.in	2007-03-22 17:24:41.000000000 -0700
+++ S-vn-gtsmall/gcc/c-config-lang.in	2007-03-22 17:27:27.000000000 -0700
@@ -23,4 +23,4 @@
 # files used by C that have garbage collection GTY macros in them
 # which therefore need to be scanned by gengtype.c.
 
-gtfiles="\$(srcdir)/c-lang.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-pragma.c \$(srcdir)/c-objc-common.c \$(srcdir)/c-parser.c"
+gtfiles="\$(srcdir)/c-lang.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-pragma.h \$(srcdir)/c-pragma.c \$(srcdir)/c-objc-common.c \$(srcdir)/c-parser.c"
Index: S-vn-gtsmall/gcc/cp/config-lang.in
===================================================================
--- S-vn-gtsmall.orig/gcc/cp/config-lang.in	2007-03-22 17:24:41.000000000 -0700
+++ S-vn-gtsmall/gcc/cp/config-lang.in	2007-03-22 17:27:27.000000000 -0700
@@ -31,4 +31,4 @@
 
 target_libs="target-libstdc++-v3"
 
-gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-lex.c \$(srcdir)/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c"
+gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-lex.c \$(srcdir)/c-pragma.h \$(srcdir)/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c"
Index: S-vn-gtsmall/gcc/gengtype.c
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype.c	2007-03-22 17:27:24.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype.c	2007-03-22 17:27:27.000000000 -0700
@@ -133,13 +133,6 @@
    (const char *input_file);
 const char *get_output_file_name (const char *);
 
-#include "gtyp-gen.h"
-
-/* A bitmap that specifies which of BASE_FILES should be used to
-   output a definition that is different for each language and must be
-   defined once in each language that uses INPUT_FILE.  */
-static lang_bitmap get_base_file_bitmap (const char *input_file);
-
 /* Print, like fprintf, to O.  */
 static void oprintf (outf_p o, const char *S, ...)
      ATTRIBUTE_PRINTF_2;
@@ -151,20 +144,12 @@
    source file.  */
 static outf_p header_file;
 
-/* Number of files specified in gtfiles.  */
-#define NUM_GT_FILES (ARRAY_SIZE (all_files) - 1)
-
-/* Number of files in the language files array.  */
-#define NUM_LANG_FILES (ARRAY_SIZE (lang_files) - 1)
+/* Source directory.  */
+static const char *srcdir;
 
 /* Length of srcdir name.  */
 static int srcdir_len = 0;
 
-/* A list of output files suitable for definitions.  There is one
-   BASE_FILES entry for each language.  */
-#define NUM_BASE_FILES (ARRAY_SIZE (lang_dir_names) - 1)
-static outf_p base_files[NUM_BASE_FILES];
-
 static outf_p create_file (const char *, const char *);
 static const char * get_file_basename (const char *);
 
@@ -210,7 +195,285 @@
 
   return result;
 }
+
+/* Input file handling. */
+
+/* Table of all input files.  */
+static const char **gt_files;
+static size_t num_gt_files;
+
+/* Vector of per-language directories.  */
+static const char **lang_dir_names;
+static size_t num_lang_dirs;
+
+/* An array of output files suitable for definitions.  There is one
+   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)
+{
+  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
+   consider repeated files.  */
+static size_t
+measure_input_list (FILE *list)
+{
+  size_t n = 0;
+  int c;
+  bool atbol = true;
+  num_lang_dirs = 0;
+  num_gt_files = 0;
+  while ((c = getc (list)) != EOF)
+    {
+      n++;
+      if (atbol)
+	{
+	  if (c == '[')
+	    num_lang_dirs++;
+	  else
+	    {
+	      /* Add space for a lang_bitmap before the input file name.  */
+	      n += sizeof (lang_bitmap);
+	      num_gt_files++;
+	    }
+	  atbol = false;
+	}
+
+      if (c == '\n')
+	atbol = true;
+    }
+
+  rewind (list);
+  return n;
+}
+
+/* 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
+   diagnostics.  */
+static bool
+read_input_line (FILE *list, char **herep, char **linep,
+		 struct fileloc *pos)
+{
+  char *here = *herep;
+  char *line;
+  int c = getc (list);
+
+  if (c == EOF)
+    {
+      *linep = 0;
+      return false;
+    }
+  else if (c == '[')
+    {
+      /* No space for a lang_bitmap is necessary.  Discard the '['. */
+      c = getc (list);
+      line = here;
+      while (c != ']' && c != '\n' && c != EOF)
+	{
+	  *here++ = c;
+	  c = getc (list);
+	}
+      *here++ = '\0';
+
+      if (c == ']')
+	{
+	  c = getc (list);  /* eat what should be a newline */
+	  if (c != '\n' && c != EOF)
+	    error_at_line (pos, "junk on line after language tag [%s]", line);
+	}
+      else
+	error_at_line (pos, "missing close bracket for language tag [%s", line);
+
+      *herep = here;
+      *linep = line;
+      return true;
+    }
+  else
+    {
+      /* Leave space for a lang_bitmap.  */
+      memset (here, 0, sizeof (lang_bitmap));
+      here += sizeof (lang_bitmap);
+      line = here;
+      do
+	{
+	  *here++ = c;
+	  c = getc (list);
+	}
+      while (c != EOF && c != '\n');
+      *here++ = '\0';
+      *herep = here;
+      *linep = line;
+      return false;
+    }
+}
+
+/* Read the list of input files from LIST and compute all of the
+   relevant tables.  There is one file per line of the list.  At
+   first, all the files on the list are language-generic, but
+   eventually a line will appear which is the name of a language
+   subdirectory in square brackets, like this: [cp].  All subsequent
+   files are specific to that language, until another language
+   subdirectory tag appears.  Files can appear more than once, if
+   they apply to more than one language.  */
+static void
+read_input_list (const char *listname)
+{
+  FILE *list = fopen (listname, "r");
+  if (!list)
+    fatal ("cannot open %s: %s", listname, strerror (errno));
+  else
+    {
+      struct fileloc epos;
+      size_t bufsz = measure_input_list (list);
+      char *buf = XNEWVEC (char, bufsz);
+      char *here = buf;
+      char *committed = buf;
+      char *limit = buf + bufsz;
+      char *line;
+      bool is_language;
+      size_t langno = 0;
+      size_t nfiles = 0;
+      lang_bitmap curlangs = (1 << num_lang_dirs) - 1;
+
+      epos.file = listname;
+      epos.line = 0;
 
+      lang_dir_names = XNEWVEC (const char *, num_lang_dirs);
+      gt_files = XNEWVEC (const char *, num_gt_files);
+
+      for (;;)
+	{
+	next_line:
+	  epos.line++;
+	  committed = here;
+	  is_language = read_input_line (list, &here, &line, &epos);
+	  gcc_assert (here <= limit);
+	  if (line == 0)
+	    break;
+	  else if (is_language)
+	    {
+	      size_t i;
+	      gcc_assert (langno <= num_lang_dirs);
+	      for (i = 0; i < langno; i++)
+		if (strcmp (lang_dir_names[i], line) == 0)
+		  {
+		    error_at_line (&epos, "duplicate language tag [%s]", line);
+		    curlangs = 1 << i;
+		    here = committed;
+		    goto next_line;
+		  }
+
+	      curlangs = 1 << langno;
+	      lang_dir_names[langno++] = line;
+	    }
+	  else
+	    {
+	      size_t i;
+	      gcc_assert (nfiles <= num_gt_files);
+	      for (i = 0; i < nfiles; i++)
+		if (strcmp (gt_files[i], line) == 0)
+		  {
+		    /* 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]);
+		    if (bmap & curlangs)
+		      error_at_line (&epos, "file %s specified more than once "
+				     "for language %s", line, langno == 0
+				     ? "(all)"
+				     : lang_dir_names[langno - 1]);
+
+		    bmap |= curlangs;
+		    set_lang_bitmap ((char *)gt_files[i], bmap);
+		    here = committed;
+		    goto next_line;
+		  }
+
+	      set_lang_bitmap (line, curlangs);
+	      gt_files[nfiles++] = line;
+	    }
+	}
+      /* Update the global counts now that we know accurately how many
+	 things there are.  (We do not bother resizing the arrays down.)  */
+      num_lang_dirs = langno;
+      num_gt_files = nfiles;
+    }
+
+  /* Sanity check: any file that resides in a language subdirectory
+     (e.g. 'cp') ought to belong to the corresponding language.
+     ??? Still true if for instance ObjC++ is enabled and C++ isn't?
+     (Can you even do that?  Should you be allowed to?)  */
+  {
+    size_t f;
+    for (f = 0; f < num_gt_files; f++)
+      {
+	lang_bitmap bitmap = get_lang_bitmap (gt_files[f]);
+	const char *basename = get_file_basename (gt_files[f]);
+	const char *slashpos = strchr (basename, '/');
+
+	if (slashpos)
+	  {
+	    size_t l;
+	    for (l = 0; l < num_lang_dirs; l++)
+	      if ((size_t)(slashpos - basename) == strlen (lang_dir_names [l])
+		  && memcmp (basename, lang_dir_names[l],
+			     strlen (lang_dir_names[l])) == 0)
+		{
+		  if (!(bitmap & (1 << l)))
+		    error ("%s is in language directory '%s' but is not "
+			   "tagged for that language",
+			   basename, lang_dir_names[l]);
+		  break;
+		}
+          }
+      }
+  }
+
+  if (ferror (list))
+    fatal ("error reading %s: %s", listname, strerror (errno));
+
+  fclose (list);
+}
+
+
+
 /* The one and only TYPE_STRING.  */
 
 static struct type string_type = {
@@ -297,7 +560,7 @@
 {
   type_p si;
   type_p s = NULL;
-  lang_bitmap bitmap = get_base_file_bitmap (pos->file);
+  lang_bitmap bitmap = get_lang_bitmap (pos->file);
 
   for (si = structures; si != NULL; si = si->next)
     if (strcmp (name, si->u.s.tag) == 0
@@ -1202,7 +1465,9 @@
 
   header_file = create_file ("GCC", "gtype-desc.h");
 
-  for (i = 0; i < NUM_BASE_FILES; i++)
+  base_files = XNEWVEC (outf_p, num_lang_dirs);
+
+  for (i = 0; i < num_lang_dirs; i++)
     base_files[i] = create_file (lang_dir_names[i],
 				 xasprintf ("gtype-%s.h", lang_dir_names[i]));
 
@@ -1242,7 +1507,7 @@
 
   basename++;
 
-  for (i = 1; i < NUM_BASE_FILES; i++)
+  for (i = 0; i < num_lang_dirs; i++)
     {
       const char * s1;
       const char * s2;
@@ -1264,63 +1529,6 @@
   return basename;
 }
 
-/* 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.  */
-
-unsigned
-get_base_file_bitmap (const char *input_file)
-{
-  const char *basename = get_file_basename (input_file);
-  const char *slashpos = strchr (basename, '/');
-  unsigned j;
-  unsigned k;
-  unsigned bitmap;
-
-  /* If the file resides in a language subdirectory (e.g., 'cp'), assume that
-     it belongs to the corresponding language.  The file may belong to other
-     languages as well (which is checked for below).  */
-
-  if (slashpos)
-    {
-      size_t i;
-      for (i = 1; i < NUM_BASE_FILES; i++)
-	if ((size_t)(slashpos - basename) == strlen (lang_dir_names [i])
-	    && memcmp (basename, lang_dir_names[i], strlen (lang_dir_names[i])) == 0)
-          {
-            /* It's in a language directory, set that language.  */
-            bitmap = 1 << i;
-          }
-    }
-
-  /* If it's in any config-lang.in, then set for the languages
-     specified.  */
-
-  bitmap = 0;
-
-  for (j = 0; j < NUM_LANG_FILES; j++)
-    {
-      if (!strcmp(input_file, lang_files[j]))
-        {
-          for (k = 0; k < NUM_BASE_FILES; k++)
-            {
-              if (!strcmp(lang_dir_names[k], langs_for_lang_files[j]))
-                bitmap |= (1 << k);
-            }
-        }
-    }
-
-  /* Otherwise, set all languages.  */
-  if (!bitmap)
-    bitmap = (1 << NUM_BASE_FILES) - 1;
-
-  return bitmap;
-}
-
 /* An output file, suitable for definitions, that can see declarations
    made in INPUT_FILE and is linked into every language that uses
    INPUT_FILE.  */
@@ -1382,7 +1590,7 @@
     {
       size_t i;
 
-      for (i = 0; i < NUM_BASE_FILES; i++)
+      for (i = 0; i < num_lang_dirs; i++)
 	if (memcmp (basename, lang_dir_names[i], strlen (lang_dir_names[i])) == 0
 	    && basename[strlen(lang_dir_names[i])] == '/')
 	  return base_files[i];
@@ -2644,7 +2852,7 @@
   for (fli2 = flp; fli2; fli2 = fli2->next)
     if (fli2->started_p)
       {
-	lang_bitmap bitmap = get_base_file_bitmap (fli2->name);
+	lang_bitmap bitmap = get_lang_bitmap (fli2->name);
 	int fnum;
 
 	for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
@@ -2660,7 +2868,7 @@
 
   {
     size_t fnum;
-    for (fnum = 0; fnum < NUM_BASE_FILES; fnum++)
+    for (fnum = 0; fnum < num_lang_dirs; fnum++)
       oprintf (base_files [fnum],
 	       "const struct %s * const %s[] = {\n",
 	       tname, name);
@@ -2670,7 +2878,7 @@
   for (fli2 = flp; fli2; fli2 = fli2->next)
     if (fli2->started_p)
       {
-	lang_bitmap bitmap = get_base_file_bitmap (fli2->name);
+	lang_bitmap bitmap = get_lang_bitmap (fli2->name);
 	int fnum;
 
 	fli2->started_p = 0;
@@ -2686,7 +2894,7 @@
 
   {
     size_t fnum;
-    for (fnum = 0; fnum < NUM_BASE_FILES; fnum++)
+    for (fnum = 0; fnum < num_lang_dirs; fnum++)
       {
 	oprintf (base_files[fnum], "  NULL\n");
 	oprintf (base_files[fnum], "};\n");
@@ -2870,7 +3078,7 @@
   d.indent = 2;
   d.line = &v->line;
   d.opt = v->opt;
-  d.bitmap = get_base_file_bitmap (v->line.file);
+  d.bitmap = get_lang_bitmap (v->line.file);
   d.param = NULL;
 
   d.prev_val[3] = prevval3 = xasprintf ("&%s", v->name);
@@ -3213,22 +3421,27 @@
 }
 
 
-extern int main (int argc, char **argv);
 int
-main (int ARG_UNUSED (argc), char ** ARG_UNUSED (argv))
+main (int argc, char **argv)
 {
-  unsigned i;
+  size_t i;
   static struct fileloc pos = { __FILE__, __LINE__ };
-  unsigned j;
 
+  /* fatal uses this */
+  progname = "gengtype";
+
+  if (argc != 3)
+    fatal ("usage: gengtype srcdir input-list");
+
+  srcdir = argv[1];
   srcdir_len = strlen (srcdir);
 
+  read_input_list (argv[2]);
+  if (hit_error)
+    return 1;
+
   scalar_char.u.scalar_is_char = true;
   scalar_nonchar.u.scalar_is_char = false;
-
-  /* fatal uses this */
-  progname = "gengtype";
-
   gen_rtx_next ();
 
   do_scalar_typedef ("CUMULATIVE_ARGS", &pos);
@@ -3247,20 +3460,9 @@
 
   do_typedef ("HARD_REG_SET", create_array (&scalar_nonchar, "2"), &pos);
 
-  for (i = 0; i < NUM_GT_FILES; i++)
+  for (i = 0; i < num_gt_files; i++)
     {
-      int dupflag = 0;
-      /* Omit if already seen.  */
-      for (j = 0; j < i; j++)
-        {
-          if (!strcmp (all_files[i], all_files[j]))
-            {
-              dupflag = 1;
-              break;
-            }
-        }
-      if (!dupflag)
-        parse_file (all_files[i]);
+      parse_file (gt_files[i]);
 #ifndef USE_MAPPED_LOCATION
       /* temporary kludge - gengtype doesn't handle conditionals.
 	 Manually add source_locus *after* we've processed input.h.  */
Index: S-vn-gtsmall/gcc/objc/config-lang.in
===================================================================
--- S-vn-gtsmall.orig/gcc/objc/config-lang.in	2007-03-22 17:24:41.000000000 -0700
+++ S-vn-gtsmall/gcc/objc/config-lang.in	2007-03-22 17:27:27.000000000 -0700
@@ -34,4 +34,4 @@
 # Most of the object files for cc1obj actually come from C.
 lang_requires="c"
 
-gtfiles="\$(srcdir)/objc/objc-act.h \$(srcdir)/c-parser.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-objc-common.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-pragma.c \$(srcdir)/objc/objc-act.c"
+gtfiles="\$(srcdir)/objc/objc-act.h \$(srcdir)/c-parser.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-objc-common.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-pragma.h \$(srcdir)/c-pragma.c \$(srcdir)/objc/objc-act.c"
Index: S-vn-gtsmall/gcc/objcp/config-lang.in
===================================================================
--- S-vn-gtsmall.orig/gcc/objcp/config-lang.in	2007-03-22 17:24:41.000000000 -0700
+++ S-vn-gtsmall/gcc/objcp/config-lang.in	2007-03-22 17:27:27.000000000 -0700
@@ -38,4 +38,4 @@
 lang_requires="objc c++"
 subdir_requires="objc cp"
 
-gtfiles="\$(srcdir)/objcp/objcp-decl.c \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-act.h \$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-lex.c \$(srcdir)/c-pragma.c \$(srcdir)/cp/cp-objcp-common.c"
+gtfiles="\$(srcdir)/objcp/objcp-decl.c \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-act.h \$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-lex.c \$(srcdir)/c-pragma.h \$(srcdir)/c-pragma.c \$(srcdir)/cp/cp-objcp-common.c"
Subject: Replace Yacc parser with recursive descent parser

Now things get *really* interesting.  This patch removes the Yacc
parser altogether and substitutes a hand-written recursive-descent
parser.  In addition to the usual advantages of this (better error
recovery, easier to maintain) we get a number of special benefits:

 - It is no longer necessary to have Bison to build GCC, unless you
   want to build treelang.
 - The new parser implements a much closer approximation to the C type
   grammar than the old one did.
 - It is practical to get rid of almost all the extra-lexical work
   being done in the lexical analyzer.
 - It is *almost* practical to scan *all* structures, whether or
   not they are tagged GTY(()) -- in other words, it is almost
   practical to eliminate the need to mark structures as GC-relevant,
   unless there are some options to be specified.  However, there
   are enough places where macro magic is going on inside structure
   definitions, requiring special casing in gengtype, that I decided
   not to do it.

The new parser does not tolerate the old kludge for the types defined
in input.h (location_t and friends).  I have instead hardwired the type
definitions into gengtype.c and suppressed the definitions in the source.
This would not be necessary if the USE_MAPPED_LOCATION transition were
completed (I am pleased to see that someone is working on it again).

CUMULATIVE_ARGS deserves special mention: some ports define it with
#define, some with typedef.  Because of this, not only does it need to
be given a fake definition in gengtype.c, any definition that we do
see in the source needs to be suppressed.  This will blow up horribly
if anyone ever defines a CUMULATIVE_ARGS structure containing fields
that need marking.  (This was a preexisting condition; I just thought
I'd point it out.)

I noticed while experimenting that there is this thing called
IFCVT_EXTRA_FIELDS, which a port could define to add fields to
struct ce_if_block.  No port does this.  Can we kill it?

The change to bitmap.h, for the record, is *not* a kludge, it
is the Right Thing and will remain so even if we do get 'round to
implementing preprocessing.

	* gengtype-parse.c: New file.
	* gengtype-yacc.y: Delete.
	* gengtype-lex.l: Don't include gengtype-yacc.h.
	Define YY_DECL and yyterminate appropriately for recursive
	descent parser.  yylval is now a string out-parameter to yylex.
	(HWS, EOID): New shorthand.
	(IWORD): Add a couple more types.
	(yylex): Add a setup stanza.  Remove the complex rules for
	detecting GTY'ed types and typedefs; replace with simple
	keyword detectors.  Adjust everything for the changed
	definition of yylval.  Ignore all pp-directives, not just #define.
	(yyerror): Delete.
	(parse_file): Rename yybegin; do not call yyparse.
	(yyend): New.
	* gengtype.c (xasprintf): Export again.
	(this_file): New.  Use everywhere __FILE__ was being used.
	(get_lang_bitmap): Special case types defined in gengtype.c.
	(do_typedef, new_structure): Suppress definition of certain types.
	(new_structure): Improve diagnostics of duplicate definitions.
	Make sure location_s is associated with input.h.
	(nreverse_pairs, define_location_structures): New functions.
	(main): Improve tagging of kludge types.  Remove old kludges
	for input.h types; use define_location_structures.
	* gengtype.h: Update prototypes.  Define token codes here.
	* Makefile.in: Remove all references to gengtype-yacc.
	Add rules for gengtype-parse.o.  Adjust rules for gengtype-lex.o
	and gengtype.

	* bitmap.h (struct bitmap_head_def): Coalesce definitions,
	add GTY((skip)) to the field that's only conditionally there.

Index: S-vn-gtsmall/gcc/Makefile.in
===================================================================
--- S-vn-gtsmall.orig/gcc/Makefile.in	2007-03-26 14:05:45.000000000 -0700
+++ S-vn-gtsmall/gcc/Makefile.in	2007-03-26 14:08:04.000000000 -0700
@@ -188,8 +188,6 @@
 
 # These files are to have specific diagnostics suppressed, or are not to
 # be subject to -Werror:
-# Bison-1.75 output often yields (harmless) -Wtraditional warnings
-build/gengtype-yacc.o-warn = -Wno-error
 # flex output may yield harmless "no previous prototype" warnings
 build/gengtype-lex.o-warn = -Wno-error
 # SYSCALLS.c misses prototypes
@@ -1699,7 +1697,7 @@
 
 srcextra: gcc.srcextra lang.srcextra
 
-gcc.srcextra: gengtype-lex.c gengtype-yacc.c gengtype-yacc.h
+gcc.srcextra: gengtype-lex.c
 	-cp -p $^ $(srcdir)
 
 c-incpath.o: c-incpath.c c-incpath.h $(CONFIG_H) $(SYSTEM_H) $(CPPLIB_H) \
@@ -3105,9 +3103,8 @@
 build/genflags.o : genflags.c $(RTL_BASE_H) $(OBSTACK_H) $(BCONFIG_H)	\
   $(SYSTEM_H) coretypes.h $(GTM_H) errors.h gensupport.h
 build/gengenrtl.o : gengenrtl.c $(BCONFIG_H) $(SYSTEM_H) rtl.def
-build/gengtype-lex.o : gengtype-lex.c gengtype.h gengtype-yacc.h	\
-  $(BCONFIG_H) $(SYSTEM_H)
-build/gengtype-yacc.o : gengtype-yacc.c gengtype.h $(BCONFIG_H)		\
+build/gengtype-lex.o : gengtype-lex.c gengtype.h $(BCONFIG_H) $(SYSTEM_H)
+build/gengtype-parse.o : gengtype-parse.c gengtype.h $(BCONFIG_H)	\
   $(SYSTEM_H)
 build/gengtype.o : gengtype.c $(BCONFIG_H) $(SYSTEM_H) gengtype.h 	\
   rtl.def insn-notes.def errors.h
@@ -3147,18 +3144,12 @@
 # These programs are not linked with the MD reader.
 build/gengenrtl$(build_exeext) : $(BUILD_ERRORS)
 build/genmodes$(build_exeext) : $(BUILD_ERRORS)
-build/gengtype$(build_exeext) : build/gengtype-lex.o \
-  build/gengtype-yacc.o $(BUILD_ERRORS)
+build/gengtype$(build_exeext) : build/gengtype-lex.o build/gengtype-parse.o \
+				$(BUILD_ERRORS)
 
 # Generated source files for gengtype.
 gengtype-lex.c : gengtype-lex.l
 	-$(FLEX) $(FLEXFLAGS) -o$@ $<
-# This is a pattern rule solely so that Make knows it need not run the
-# command twice.  The modifier to $@ ensures that Bison is asked to
-# produce a .c file, whether or not Make decides it needs the .h file
-# first.
-gengtype-y%.c gengtype-y%.h: gengtype-y%.y
-	-$(BISON) $(BISONFLAGS) -d -o $(@:.h=.c) $<
 
 #
 # Remake internationalization support.
Index: S-vn-gtsmall/gcc/gengtype-yacc.y
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype-yacc.y	2007-03-26 14:01:52.000000000 -0700
+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
@@ -1,227 +0,0 @@
-/* -*- indented-text -*- */
-/* Process source files and output type information.
-   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
-
-%{
-#include "bconfig.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "gengtype.h"
-#define YYERROR_VERBOSE
-%}
-
-%union {
-  type_p t;
-  pair_p p;
-  options_p o;
-  const char *s;
-}
-
-%token <s>ENT_TYPEDEF_STRUCT
-%token <s>ENT_STRUCT
-%token <s>ENT_TYPEDEF_UNION
-%token <s>ENT_UNION
-%token ENT_EXTERNSTATIC
-%token GTY_TOKEN
-%token VEC_TOKEN
-%token UNION
-%token STRUCT
-%token ENUM
-%token ALIAS
-%token NESTED_PTR
-%token <s>PARAM_IS
-%token NUM
-%token <s>SCALAR
-%token <s>ID
-%token <s>STRING
-%token <s>ARRAY
-%token <s>CHAR
-
-%type <p> struct_fields
-%type <t> type lasttype
-%type <o> optionsopt options optionseq
-%type <s> type_option stringseq
-
-%%
-
-start: /* empty */
-       | typedef_struct start
-       | externstatic start
-       | start
-       ;
-
-typedef_struct: ENT_TYPEDEF_STRUCT options '{' struct_fields '}' ID
-		   {
-		     type_p t = new_structure ($1, false, &lexer_line, $4, $2);
-		     do_typedef ($6, t, &lexer_line);
-		     lexer_toplevel_done = 1;
-		   }
-		  ';'
-		| ENT_TYPEDEF_UNION options '{' struct_fields '}' ID
-		   {
-		     type_p t = new_structure ($1, true, &lexer_line, $4, $2);
-		     do_typedef ($6, t, &lexer_line);
-		     lexer_toplevel_done = 1;
-		   }
-		  ';'
-		| ENT_STRUCT options '{' struct_fields '}'
-		   {
-		     new_structure ($1, false, &lexer_line, $4, $2);
-		     lexer_toplevel_done = 1;
-		   }
-		  ';'
-		| ENT_UNION options '{' struct_fields '}'
-		   {
-		     new_structure ($1, true, &lexer_line, $4, $2);
-		     lexer_toplevel_done = 1;
-		   }
-		  ';'
-		;
-
-externstatic: ENT_EXTERNSTATIC options lasttype ID semiequal
-	         {
-	           note_variable ($4, adjust_field_type ($3, $2), $2,
-				  &lexer_line);
-	         }
-	      | ENT_EXTERNSTATIC options lasttype ID ARRAY semiequal
-	         {
-	           note_variable ($4, create_array ($3, $5),
-	      		    $2, &lexer_line);
-	         }
-	      | ENT_EXTERNSTATIC options lasttype ID ARRAY ARRAY semiequal
-	         {
-	           note_variable ($4, create_array (create_array ($3, $6),
-	      				      $5),
-	      		    $2, &lexer_line);
-	         }
-	      ;
-
-lasttype: type
-	    {
-	      lexer_toplevel_done = 1;
-	      $$ = $1;
-	    }
-	    ;
-
-semiequal: ';'
-	   | '='
-	   ;
-
-struct_fields: { $$ = NULL; }
-	       | type optionsopt ID bitfieldopt ';' struct_fields
-	          {
-		    $$ = create_field_at ($6, $1, $3, $2, &lexer_line);
-		  }
-	       | type optionsopt ID ARRAY ';' struct_fields
-	          {
-		    $$ = create_field_at ($6, create_array ($1, $4),
-		    			  $3, $2, &lexer_line);
-		  }
-	       | type optionsopt ID ARRAY ARRAY ';' struct_fields
-	          {
-		    type_p arr = create_array (create_array ($1, $5), $4);
-		    $$ = create_field_at ($7, arr, $3, $2, &lexer_line);
-		  }
-	       | type ':' bitfieldlen ';' struct_fields
-		  { $$ = $5; }
-	       ;
-
-bitfieldopt: /* empty */
-	     | ':' bitfieldlen
-	     ;
-
-bitfieldlen: NUM | ID
-		{ }
-	     ;
-
-type: SCALAR
-         { $$ = create_scalar_type ($1); }
-      | ID
-         { $$ = resolve_typedef ($1, &lexer_line); }
-      | VEC_TOKEN '(' ID ',' ID ')'
-         { $$ = resolve_typedef (concat ("VEC_", $3, "_", $5, (char *)0),
-	      			 &lexer_line); }
-      | type '*'
-         { $$ = create_pointer ($1); }
-      | STRUCT ID '{' struct_fields '}'
-         { $$ = new_structure ($2, 0, &lexer_line, $4, NULL); }
-      | STRUCT ID
-         { $$ = find_structure ($2, 0); }
-      | UNION ID '{' struct_fields '}'
-         { $$ = new_structure ($2, 1, &lexer_line, $4, NULL); }
-      | UNION ID
-         { $$ = find_structure ($2, 1); }
-      | ENUM ID
-         { $$ = create_scalar_type ($2); }
-      | ENUM ID '{' enum_items '}'
-         { $$ = create_scalar_type ($2); }
-      ;
-
-enum_items: /* empty */
-	    | ID '=' NUM ',' enum_items
-	      { }
-	    | ID ',' enum_items
-	      { }
-	    | ID enum_items
-	      { }
-	    ;
-
-optionsopt: { $$ = NULL; }
-	    | options { $$ = $1; }
-	    ;
-
-options: GTY_TOKEN '(' '(' optionseq ')' ')'
-	   { $$ = $4; }
-	 ;
-
-type_option : ALIAS
-	        { $$ = "ptr_alias"; }
-	      | PARAM_IS
-	        { $$ = $1; }
-	      ;
-
-optionseq: { $$ = NULL; }
-	| optionseq commaopt ID
-	   { $$ = create_option ($1, $3, (void *)""); }
-	| optionseq commaopt ID '(' stringseq ')'
-	   { $$ = create_option ($1, $3, (void *)$5); }
-	| optionseq commaopt type_option '(' type ')'
-	   { $$ = create_option ($1, $3, adjust_field_type ($5, 0)); }
-	| optionseq commaopt NESTED_PTR '(' type ',' stringseq ',' stringseq ')'
-	   { $$ = create_nested_ptr_option ($1, $5, $7, $9); }
-
-commaopt: /* nothing */
-	  | ','
-	  ;
-
-stringseq: STRING
-	     { $$ = $1; }
-	   | stringseq STRING
-	     {
-	       size_t l1 = strlen ($1);
-	       size_t l2 = strlen ($2);
-	       char *s = XRESIZEVEC (char, $1, l1 + l2 + 1);
-	       memcpy (s + l1, $2, l2 + 1);
-	       XDELETE ($2);
-	       $$ = s;
-	     }
-	   ;
-%%
Index: S-vn-gtsmall/gcc/gengtype-parse.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ S-vn-gtsmall/gcc/gengtype-parse.c	2007-03-26 14:08:04.000000000 -0700
@@ -0,0 +1,929 @@
+/* Process source files and output type information.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
+
+#include "bconfig.h"
+#include "system.h"
+#include "gengtype.h"
+
+/* This is a simple recursive-descent parser which understands a subset of
+   the C type grammar.
+
+   Rule functions are suffixed _seq if they scan a sequence of items;
+   _opt if they may consume zero tokens; _seqopt if both are true.  The
+   "consume_" prefix indicates that a sequence of tokens is parsed for
+   syntactic correctness and then thrown away.  */
+
+/* Simple one-token lookahead mechanism.  */
+
+struct token
+{
+  const char *value;
+  int code;
+  bool valid;
+};
+static struct token T;
+
+/* Retrieve the code of the current token; if there is no current token,
+   get the next one from the lexer.  */
+static inline int
+token (void)
+{
+  if (!T.valid)
+    {
+      T.code = yylex (&T.value);
+      T.valid = true;
+    }
+  return T.code;
+}
+
+/* Retrieve the value of the current token (if any) and mark it consumed.
+   The next call to token() will get another token from the lexer.  */
+static inline const char *
+advance (void)
+{
+  T.valid = false;
+  return T.value;
+}
+
+/* Diagnostics.  */
+
+/* This array is indexed by the token code minus CHAR_TOKEN_OFFSET.  */
+static const char *const token_names[] = {
+  "GTY",
+  "typedef",
+  "extern",
+  "static",
+  "union",
+  "struct",
+  "enum",
+  "VEC",
+  "DEF_VEC_[OP]",
+  "DEF_VEC_I",
+  "DEF_VEC_ALLOC_[IOP]",
+  "...",
+  "ptr_alias",
+  "nested_ptr",
+  "a param<N>_is option",
+  "a number",
+  "a scalar type",
+  "an identifier",
+  "a string constant",
+  "a character constant",
+  "an array declarator",
+};
+
+/* This array is indexed by token code minus FIRST_TOKEN_WITH_VALUE.  */
+static const char *const token_value_format[] = {
+  "%s",
+  "'%s'",
+  "'%s'",
+  "'%s'",
+  "'\"%s\"'",
+  "\"'%s'\"",
+  "'[%s]'",
+};
+
+/* Produce a printable representation for a token defined by CODE and
+   VALUE.  This sometimes returns pointers into malloc memory and
+   sometimes not, therefore it is unsafe to free the pointer it
+   returns, so that memory is leaked.  This does not matter, as this
+   function is only used for diagnostics, and in a successful run of
+   the program there will be none.  */
+static const char *
+print_token (int code, const char *value)
+{
+  if (code < CHAR_TOKEN_OFFSET)
+    return xasprintf ("'%c'", code);
+  else if (code < FIRST_TOKEN_WITH_VALUE)
+    return xasprintf ("'%s'", token_names[code - CHAR_TOKEN_OFFSET]);
+  else if (!value)
+    return token_names[code - CHAR_TOKEN_OFFSET]; /* don't quote these */
+  else
+    return xasprintf (token_value_format[code - FIRST_TOKEN_WITH_VALUE],
+		      value);
+}
+
+/* Convenience wrapper around print_token which produces the printable
+   representation of the current token.  */
+static inline const char *
+print_cur_token (void)
+{
+  return print_token (T.code, T.value);
+}
+
+/* Report a parse error on the current line, with diagnostic MSG.
+   Behaves as standard printf with respect to additional arguments and
+   format escapes.  */
+static void ATTRIBUTE_PRINTF_1
+parse_error (const char *msg, ...)
+{
+  va_list ap;
+
+  fprintf (stderr, "%s:%d: parse error: ", lexer_line.file, lexer_line.line);
+
+  va_start (ap, msg);
+  vfprintf (stderr, msg, ap);
+  va_end (ap);
+
+  hit_error = true;
+}
+
+/* If the next token does not have code T, report a parse error; otherwise
+   return the token's value.  */
+static const char *
+require (int t)
+{
+  int u = token ();
+  const char *v = advance ();
+  if (u != t)
+    {
+      parse_error ("expected %s, have %s",
+		   print_token (t, 0), print_token (u, v));
+      return 0;
+    }
+  return v;
+}
+
+/* If the next token does not have one of the codes T1 or T2, report a
+   parse error; otherwise return the token's value.  */
+static const char *
+require2 (int t1, int t2)
+{
+  int u = token ();
+  const char *v = advance ();
+  if (u != t1 && u != t2)
+    {
+      parse_error ("expected %s or %s, have %s",
+		   print_token (t1, 0), print_token (t2, 0),
+		   print_token (u, v));
+      return 0;
+    }
+  return v;
+}
+
+/* Near-terminals.  */
+
+/* C-style string constant concatenation: STRING+
+   Bare STRING should appear nowhere else in this file.  */
+static const char *
+string_seq (void)
+{
+  const char *s1, *s2;
+  size_t l1, l2;
+  char *buf;
+
+  s1 = require (STRING);
+  if (s1 == 0)
+    return "";
+  while (token () == STRING)
+    {
+      s2 = advance ();
+
+      l1 = strlen (s1);
+      l2 = strlen (s2);
+      buf = XRESIZEVEC (char, s1, l1 + l2 + 1);
+      memcpy (buf + l1, s2, l2 + 1);
+      XDELETE (s2);
+      s1 = buf;
+    }
+  return s1;
+}
+
+/* typedef_name: either an ID, or VEC(x,y) which is translated to VEC_x_y.
+   Use only where VEC(x,y) is legitimate, i.e. in positions where a
+   typedef name may appear.  */
+static const char *
+typedef_name (void)
+{
+  if (token () == VEC_TOKEN)
+    {
+      const char *c1, *c2, *r;
+      advance ();
+      require ('(');
+      c1 = require2 (ID, SCALAR);
+      require (',');
+      c2 = require (ID);
+      require (')');
+      r = concat ("VEC_", c1, "_", c2, (char *)0);
+      free ((void *)c1);
+      free ((void *)c2);
+      return r;
+    }
+  else
+    return require (ID);
+}
+
+/* Absorb a sequence of tokens delimited by balanced ()[]{}.  */
+static void
+consume_balanced (int opener, int closer)
+{
+  require (opener);
+  for (;;)
+    switch (token ())
+      {
+      default: advance (); break;
+      case '(': consume_balanced ('(',')'); break;
+      case '[': consume_balanced ('[',']'); break;
+      case '{': consume_balanced ('{','}'); break;
+
+      case '}':
+      case ']':
+      case ')':
+	if (token () != closer)
+	  parse_error ("unbalanced delimiters - expected '%c', have '%c'",
+		       closer, token ());
+	advance ();
+	return;
+
+      case EOF_TOKEN:
+	parse_error ("unexpected end of file within %c%c-delimited construct",
+		     opener, closer);
+	return;
+      }
+}
+
+/* Absorb a sequence of tokens, possibly including ()[]{}-delimited
+   expressions, until we encounter a semicolon outside any such
+   delimiters; absorb that too.  If IMMEDIATE is true, it is an error
+   if the semicolon is not the first token encountered.  */
+static void
+consume_until_semi (bool immediate)
+{
+  if (immediate && token () != ';')
+    require (';');
+  for (;;)
+    switch (token ())
+      {
+      case ';':	advance (); return;
+      default:	advance (); break;
+
+      case '(':	consume_balanced ('(',')'); break;
+      case '[': consume_balanced ('[',']'); break;
+      case '{':	consume_balanced ('{','}'); break;
+
+      case '}':
+      case ']':
+      case ')':
+	parse_error ("unmatched '%c' while scanning for ';'", token ());
+	return;
+
+      case EOF_TOKEN:
+	parse_error ("unexpected end of file while scanning for ';'");
+	return;
+      }
+}
+
+/* Absorb a sequence of tokens, possibly including ()[]{}-delimited
+   expressions, until we encounter a comma or semicolon outside any
+   such delimiters; absorb that too.  If IMMEDIATE is true, it is an
+   error if the comma or semicolon is not the first token encountered.
+   Returns true if the loop ended with a comma.  */
+static bool
+consume_until_comma_or_semi (bool immediate)
+{
+  if (immediate && token () != ',' && token () != ';')
+    require2 (',', ';');
+  for (;;)
+    switch (token ())
+      {
+      case ',':	advance (); return true;
+      case ';':	advance (); return false;
+      default:	advance (); break;
+
+      case '(':	consume_balanced ('(',')'); break;
+      case '[': consume_balanced ('[',']'); break;
+      case '{':	consume_balanced ('{','}'); break;
+
+      case '}':
+      case ']':
+      case ')':
+	parse_error ("unmatched '%s' while scanning for ',' or ';'",
+		     print_cur_token ());
+	return false;
+
+      case EOF_TOKEN:
+	parse_error ("unexpected end of file while scanning for ',' or ';'");
+	return false;
+      }
+}
+
+
+/* GTY(()) option handling.  */
+static type_p type (options_p *optsp, bool nested);
+
+/* Optional parenthesized string: ('(' string_seq ')')? */
+static options_p
+str_optvalue_opt (options_p prev)
+{
+  const char *name = advance ();
+  const char *value = "";
+  if (token () == '(')
+    {
+      advance ();
+      value = string_seq ();
+      require (')');
+    }
+  return create_option (prev, name, value);
+}
+
+/* absdecl: type '*'*
+   -- a vague approximation to what the C standard calls an abstract
+   declarator.  The only kinds that are actually used are those that
+   are just a bare type and those that have trailing pointer-stars.
+   Further kinds should be implemented if and when they become
+   necessary.  Used only within GTY(()) option values, therefore
+   further GTY(()) tags within the type are invalid.  Note that the
+   return value has already been run through adjust_field_type.  */
+static type_p
+absdecl (void)
+{
+  type_p ty;
+  options_p opts;
+
+  ty = type (&opts, true);
+  while (token () == '*')
+    {
+      ty = create_pointer (ty);
+      advance ();
+    }
+
+  if (opts)
+    parse_error ("nested GTY(()) options are invalid");
+
+  return adjust_field_type (ty, 0);
+}
+
+/* Type-option: '(' absdecl ')' */
+static options_p
+type_optvalue (options_p prev, const char *name)
+{
+  type_p ty;
+  require ('(');
+  ty = absdecl ();
+  require (')');
+  return create_option (prev, name, ty);
+}
+
+/* Nested pointer data: '(' type '*'* ',' string_seq ',' string_seq ')' */
+static options_p
+nestedptr_optvalue (options_p prev)
+{
+  type_p ty;
+  const char *from, *to;
+
+  require ('(');
+  ty = absdecl ();
+  require (',');
+  to = string_seq ();
+  require (',');
+  from = string_seq ();
+  require (')');
+
+  return create_nested_ptr_option (prev, ty, to, from);
+}
+
+/* One GTY(()) option:
+         ID str_optvalue_opt
+       | PTR_ALIAS type_optvalue
+       | PARAM_IS type_optvalue
+       | NESTED_PTR nestedptr_optvalue
+ */
+static options_p
+option (options_p prev)
+{
+  switch (token ())
+    {
+    case ID:
+      return str_optvalue_opt (prev);
+
+    case PTR_ALIAS:
+      advance ();
+      return type_optvalue (prev, "ptr_alias");
+
+    case PARAM_IS:
+      return type_optvalue (prev, advance ());
+
+    case NESTED_PTR:
+      advance ();
+      return nestedptr_optvalue (prev);
+
+    default:
+      parse_error ("expected an option keyword, have %s",
+		   print_cur_token ());
+      advance ();
+      return create_option (prev, "", "");
+    }
+}
+
+/* One comma-separated list of options.  */
+static options_p
+option_seq (void)
+{
+  options_p o;
+
+  o = option (0);
+  while (token () == ',')
+    {
+      advance ();
+      o = option (o);
+    }
+  return o;
+}
+
+/* GTY marker: 'GTY' '(' '(' option_seq? ')' ')' */
+static options_p
+gtymarker (void)
+{
+  options_p result = 0;
+  require (GTY_TOKEN);
+  require ('(');
+  require ('(');
+  if (token () != ')')
+    result = option_seq ();
+  require (')');
+  require (')');
+  return result;
+}
+
+/* Optional GTY marker.  */
+static options_p
+gtymarker_opt (void)
+{
+  if (token () != GTY_TOKEN)
+    return 0;
+  return gtymarker ();
+}
+
+/* Declarators. The logic here is largely lifted from c-parser.c.
+   Note that we do not have to process abstract declarators, which can
+   appear only in parameter type lists or casts (but see absdecl,
+   above).  Also, type qualifiers are thrown out in gengtype-lex.l so
+   we don't have to do it.  */
+
+/* array_and_function_declarators_opt:
+      \epsilon
+      array_and_function_declarators_opt ARRAY
+      array_and_function_declarators_opt '(' ... ')'
+
+   where '...' indicates stuff we ignore except insofar as grouping
+   symbols ()[]{} must balance.
+
+   Subroutine of direct_declarator - do not use elsewhere. */
+
+static type_p
+array_and_function_declarators_opt (type_p ty)
+{
+  if (token () == ARRAY)
+    {
+      const char *array = advance ();
+      return create_array (array_and_function_declarators_opt (ty), array);
+    }
+  else if (token () == '(')
+    {
+      /* We don't need exact types for functions.  */
+      consume_balanced ('(', ')');
+      array_and_function_declarators_opt (ty);
+      return create_scalar_type ("function type");
+    }
+  else
+    return ty;
+}
+
+static type_p inner_declarator (type_p, const char **, options_p *);
+
+/* direct_declarator:
+      '(' inner_declarator ')'
+      gtymarker_opt ID array_and_function_declarators_opt
+
+   Subroutine of declarator, mutually recursive with inner_declarator;
+   do not use elsewhere.  */
+static type_p
+direct_declarator (type_p ty, const char **namep, options_p *optsp)
+{
+  /* The first token in a direct-declarator must be an ID, a
+     GTY marker, or an open parenthesis.  */
+  switch (token ())
+    {
+    case GTY_TOKEN:
+      *optsp = gtymarker ();
+      /* fall through */
+    case ID:
+      *namep = require (ID);
+      break;
+
+    case '(':
+      advance ();
+      ty = inner_declarator (ty, namep, optsp);
+      require (')');
+      break;
+
+    default:
+      parse_error ("expected '(', 'GTY', or an identifier, have %s",
+		   print_cur_token ());
+      /* Do _not_ advance if what we have is a close squiggle brace, as
+	 we will get much better error recovery that way.  */
+      if (token () != '}')
+	advance ();
+      return 0;
+    }
+  return array_and_function_declarators_opt (ty);
+}
+
+/* The difference between inner_declarator and declarator is in the
+   handling of stars.  Consider this declaration:
+
+      char * (*pfc) (void)
+
+   It declares a pointer to a function that takes no arguments and
+   returns a char*.  To construct the correct type for this
+   declaration, the star outside the parentheses must be processed
+   _before_ the function type, the star inside the parentheses must
+   be processed _after_ the function type.  To accomplish this,
+   declarator() creates pointers before recursing (it is actually
+   coded as a while loop), whereas inner_declarator() recurses before
+   creating pointers.  */
+
+/* inner_declarator:
+     '*' inner_declarator
+     direct_declarator
+
+   Mutually recursive subroutine of direct_declarator; do not use
+   elsewhere.  */
+
+static type_p
+inner_declarator (type_p ty, const char **namep, options_p *optsp)
+{
+  if (token () == '*')
+    {
+      type_p inner;
+      advance ();
+      inner = inner_declarator (ty, namep, optsp);
+      if (inner == 0)
+	return 0;
+      else
+	return create_pointer (ty);
+    }
+  else
+    return direct_declarator (ty, namep, optsp);
+}
+
+/* declarator: '*'+ direct_declarator
+
+   This is the sole public interface to this part of the grammar.
+   Arguments are the type known so far, a pointer to where the name
+   may be stored, and a pointer to where GTY options may be stored.
+   Returns the final type. */
+
+static type_p
+declarator (type_p ty, const char **namep, options_p *optsp)
+{
+  *namep = 0;
+  *optsp = 0;
+  while (token () == '*')
+    {
+      advance ();
+      ty = create_pointer (ty);
+    }
+  return direct_declarator (ty, namep, optsp);
+}
+
+/* Types and declarations.  */
+
+/* Structure field(s) declaration:
+   (
+       type bitfield ';'
+     | type declarator bitfield? ( ',' declarator bitfield? )+ ';'
+   )+
+
+   Knows that such declarations must end with a close brace (or,
+   erroneously, at EOF).
+ */
+static pair_p
+struct_field_seq (void)
+{
+  pair_p f = 0;
+  type_p ty, dty;
+  options_p opts, dopts;
+  const char *name;
+  bool another;
+
+  do
+    {
+      ty = type (&opts, true);
+      /* Another piece of the IFCVT_EXTRA_FIELDS special case, see type().  */
+      if (!ty && token () == '}')
+	break;
+
+      if (!ty || token () == ':')
+	{
+	  consume_until_semi (false);
+	  continue;
+	}
+
+      do
+	{
+	  dty = declarator (ty, &name, &dopts);
+	  /* There could be any number of weird things after the declarator,
+	     notably bitfield declarations and __attribute__s.  If this
+	     function returns true, the last thing was a comma, so we have
+	     more than one declarator paired with the current type.  */
+	  another = consume_until_comma_or_semi (false);
+
+	  if (!dty)
+	    continue;
+
+	  if (opts && dopts)
+	    parse_error ("two GTY(()) options for field %s", name);
+	  if (opts && !dopts)
+	    dopts = opts;
+
+	  f = create_field_at (f, dty, name, dopts, &lexer_line);
+	}
+      while (another);
+    }
+  while (token () != '}' && token () != EOF_TOKEN);
+  return nreverse_pairs (f);
+}
+
+/* This is called type(), but what it parses (sort of) is what C calls
+   declaration-specifiers and specifier-qualifier-list:
+
+     SCALAR
+   | ID     // typedef
+   | (STRUCT|UNION) ID? gtymarker? ( '{' gtymarker? struct_field_seq '}' )?
+   | ENUM ID ( '{' ... '}' )?
+
+   Returns a partial type; under some conditions (notably
+   "struct foo GTY((...)) thing;") it may write an options
+   structure to *OPTSP.
+ */
+static type_p
+type (options_p *optsp, bool nested)
+{
+  const char *s;
+  bool is_union;
+  *optsp = 0;
+  switch (token ())
+    {
+    case SCALAR:
+      s = advance ();
+      return create_scalar_type (s);
+
+    case ID:
+    case VEC_TOKEN:
+      s = typedef_name ();
+      return resolve_typedef (s, &lexer_line);
+
+    case STRUCT:
+    case UNION:
+      {
+	options_p opts = 0;
+
+	is_union = (token() == UNION);
+	advance ();
+
+	if (token () == ID)
+	  s = advance ();
+	else
+	  s = xasprintf ("anonymous:%s:%d", lexer_line.file, lexer_line.line);
+
+	/* Top-level structures that are not explicitly tagged GTY(())
+	   are treated as mere forward declarations.  This is because
+	   there are a lot of structures that we don't need to know
+	   about, and some of those have weird macro stuff in them
+	   that we can't handle.  */
+	if (nested || token () == GTY_TOKEN)
+	  {
+	    opts = gtymarker_opt ();
+	    if (token () == '{')
+	      {
+		pair_p fields;
+		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);
+      }
+
+    case ENUM:
+      advance ();
+	if (token () == ID)
+	  s = advance ();
+	else
+	  s = xasprintf ("anonymous:%s:%d", lexer_line.file, lexer_line.line);
+
+      if (token () == '{')
+	consume_balanced ('{','}');
+      return create_scalar_type (s);
+
+    default:
+      parse_error ("expected a type specifier, have %s", print_cur_token ());
+      advance ();
+      return create_scalar_type ("erroneous type");
+    }
+}
+
+/* Top level constructs.  */
+
+/* Dispatch declarations beginning with 'typedef'.  */
+
+static void
+typedef_decl (void)
+{
+  type_p ty, dty;
+  const char *name;
+  options_p opts;
+  bool another;
+
+  gcc_assert (token () == TYPEDEF);
+  advance ();
+
+  ty = type (&opts, false);
+  if (!ty)
+    return;
+  if (opts)
+    parse_error ("GTY((...)) cannot be applied to a typedef");
+  do
+    {
+      dty = declarator (ty, &name, &opts);
+      if (opts)
+	parse_error ("GTY((...)) cannot be applied to a typedef");
+
+      /* Yet another place where we could have junk (notably attributes)
+	 after the declarator.  */
+      another = consume_until_comma_or_semi (false);
+      if (dty)
+	do_typedef (name, dty, &lexer_line);
+    }
+  while (another);
+}
+
+/* Structure definition: type() does all the work.  */
+
+static void
+struct_or_union (void)
+{
+  options_p dummy;
+  type (&dummy, false);
+  /* There may be junk after the type: notably, we cannot currently
+     distinguish 'struct foo *function(prototype);' from 'struct foo;'
+     ...  we could call declarator(), but it's a waste of time at
+     present.  Instead, just eat whatever token is currently lookahead
+     and go back to lexical skipping mode. */
+  advance ();
+}
+
+/* GC root declaration:
+     (extern|static) gtymarker? type ID array_declarators_opt (';'|'=')
+   If the gtymarker is not present, we ignore the rest of the declaration.  */
+static void
+extern_or_static (void)
+{
+  options_p opts, opts2, dopts;
+  type_p ty, dty;
+  const char *name;
+  require2 (EXTERN, STATIC);
+
+  if (token () != GTY_TOKEN)
+    {
+      advance ();
+      return;
+    }
+
+  opts = gtymarker ();
+  ty   = type (&opts2, true);  /* if we get here, it's got a GTY(()) */
+  dty  = declarator (ty, &name, &dopts);
+
+  if ((opts && dopts) || (opts && opts2) || (opts2 && dopts))
+    parse_error ("GTY((...)) specified more than once for %s", name);
+  else if (opts2)
+    opts = opts2;
+  else if (dopts)
+    opts = dopts;
+
+  if (dty)
+    {
+      note_variable (name, adjust_field_type (dty, opts), opts, &lexer_line);
+      require2 (';', '=');
+    }
+}
+
+/* Definition of a generic VEC structure:
+
+   'DEF_VEC_[IPO]' '(' id ')' ';'
+
+   Scalar VECs require slightly different treatment than otherwise -
+   that's handled in note_def_vec, we just pass it along.*/
+static void
+def_vec (void)
+{
+  bool is_scalar = (token() == DEFVEC_I);
+  const char *type;
+
+  require2 (DEFVEC_OP, DEFVEC_I);
+  require ('(');
+  type = require2 (ID, SCALAR);
+  require (')');
+  require (';');
+
+  if (!type)
+    return;
+
+  note_def_vec (type, is_scalar, &lexer_line);
+  note_def_vec_alloc (type, "none", &lexer_line);
+}
+
+/* Definition of an allocation strategy for a VEC structure:
+
+   'DEF_VEC_ALLOC_[IPO]' '(' id ',' id ')' ';'
+
+   For purposes of gengtype, this just declares a wrapper structure.  */
+static void
+def_vec_alloc (void)
+{
+  const char *type, *astrat;
+
+  require (DEFVEC_ALLOC);
+  require ('(');
+  type = require2 (ID, SCALAR);
+  require (',');
+  astrat = require (ID);
+  require (')');
+  require (';');
+
+  if (!type || !astrat)
+    return;
+
+  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.  */
+void
+parse_file (const char *fname)
+{
+  yybegin (fname);
+  for (;;)
+    {
+      switch (token ())
+	{
+	case EXTERN:
+	case STATIC:
+	  extern_or_static ();
+	  break;
+
+	case STRUCT:
+	case UNION:
+	  struct_or_union ();
+	  break;
+
+	case TYPEDEF:
+	  typedef_decl ();
+	  break;
+
+	case DEFVEC_OP:
+	case DEFVEC_I:
+	  def_vec ();
+	  break;
+
+	case DEFVEC_ALLOC:
+	  def_vec_alloc ();
+	  break;
+
+	case EOF_TOKEN:
+	  goto eof;
+
+	default:
+	  parse_error ("unexpected top level token, %s", print_cur_token ());
+	  goto eof;
+	}
+      lexer_toplevel_done = 1;
+    }
+
+ eof:
+  advance ();
+  yyend ();
+}
Index: S-vn-gtsmall/gcc/bitmap.h
===================================================================
--- S-vn-gtsmall.orig/gcc/bitmap.h	2007-03-26 13:32:50.000000000 -0700
+++ S-vn-gtsmall/gcc/bitmap.h	2007-03-26 14:08:04.000000000 -0700
@@ -70,29 +70,20 @@
 } bitmap_element;
 
 struct bitmap_descriptor;
-/* Head of bitmap linked list.  
-   The gengtype doesn't cope with ifdefs inside the definition,
-   but for statistics we need bitmap descriptor pointer in.
-   Trick it by two copies of the definition.  This is safe
-   because the bitmap descriptor is not grabagecollected.  */
-#ifndef GATHER_STATISTICS
+/* Head of bitmap linked list.  gengtype ignores ifdefs, but for
+   statistics we need to add a bitmap descriptor pointer.  As it is
+   not collected, we can just GTY((skip)) it.   */
+
 typedef struct bitmap_head_def GTY(()) {
   bitmap_element *first;	/* First element in linked list.  */
   bitmap_element *current;	/* Last element looked at.  */
   unsigned int indx;		/* Index of last element looked at.  */
   bitmap_obstack *obstack;	/* Obstack to allocate elements from.
 				   If NULL, then use ggc_alloc.  */
-} bitmap_head;
-#else
-typedef struct bitmap_head_def {
-  bitmap_element *first;	/* First element in linked list.  */
-  bitmap_element *current;	/* Last element looked at.  */
-  unsigned int indx;		/* Index of last element looked at.  */
-  bitmap_obstack *obstack;	/* Obstack to allocate elements from.
-				   If NULL, then use ggc_alloc.  */
-  struct bitmap_descriptor *desc;
-} bitmap_head;
+#ifndef GATHER_STATISTICS
+  struct bitmap_descriptor GTY((skip)) *desc;
 #endif
+} bitmap_head;
 
 /* Global data */
 extern bitmap_element bitmap_zero_bits;	/* Zero bitmap element */
Index: S-vn-gtsmall/gcc/gengtype-lex.l
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype-lex.l	2007-03-26 13:58:21.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype-lex.l	2007-03-26 14:08:04.000000000 -0700
@@ -27,7 +27,9 @@
 #define realloc xrealloc
 
 #include "gengtype.h"
-#include "gengtype-yacc.h"
+
+#define YY_DECL int yylex (const char **yylval)
+#define yyterminate() return EOF_TOKEN
 
 struct fileloc lexer_line;
 int lexer_toplevel_done;
@@ -44,199 +46,58 @@
 
 ID	[[:alpha:]_][[:alnum:]_]*
 WS	[[:space:]]+
-IWORD	short|long|(un)?signed|char|int|HOST_WIDE_INT|HOST_WIDEST_INT|bool|size_t|BOOL_BITFIELD
+HWS	[ \t\r\v\f]*
+IWORD	short|long|(un)?signed|char|int|HOST_WIDE_INT|HOST_WIDEST_INT|bool|size_t|BOOL_BITFIELD|CPPCHAR_SIGNED_T|ino_t|dev_t
 ITYPE	{IWORD}({WS}{IWORD})*
+EOID	[^[:alnum:]_]
 
 %x in_struct in_struct_comment in_comment
 %option warn noyywrap nounput nodefault perf-report
 %option 8bit never-interactive
 %%
+  /* Do this on entry to yylex():  */
+  *yylval = 0;
+  if (lexer_toplevel_done)
+    {
+      BEGIN(INITIAL);
+      lexer_toplevel_done = 0;
+    }
 
-[^[:alnum:]_]typedef{WS}(struct|union){WS}{ID}{WS}?[*[:space:]]{WS}?{ID}{WS}?";" {
-  char *tagstart;
-  size_t taglen;
-  char *namestart;
-  size_t namelen;
-  int is_pointer = 0;
-  struct type *t;
-  int union_p;
-
-  tagstart = yytext + strlen (" typedef ");
-  while (ISSPACE (*tagstart))
-    tagstart++;
-  union_p = tagstart[0] == 'u';
-  tagstart += strlen ("union ");
-  while (ISSPACE (*tagstart))
-    tagstart++;
-  for (taglen = 1; ISIDNUM (tagstart[taglen]); taglen++)
-    ;
-  for (namestart = tagstart + taglen; 
-       ! ISIDNUM (*namestart);
-       namestart++)
-    if (*namestart == '*')
-      is_pointer = 1;
-  for (namelen = 1; ISIDNUM (namestart[namelen]); namelen++)
-    ;
-  t = find_structure ((const char *) xmemdup (tagstart, taglen, taglen+1),
-		      union_p);
-  if (is_pointer)
-    t = create_pointer (t);
-  namestart = (char *) xmemdup (namestart, namelen, namelen+1);
-#ifdef USE_MAPPED_LOCATION
-  /* temporary kludge - gentype doesn't handle cpp conditionals */
-  if (strcmp (namestart, "location_t") != 0
-      && strcmp (namestart, "expanded_location") != 0)
-#endif
-  do_typedef (namestart, t, &lexer_line);
-  update_lineno (yytext, yyleng);
+  /* Things we look for in skipping mode: */
+<INITIAL>{
+^typedef/{EOID} {
+  BEGIN(in_struct);
+  return TYPEDEF;
 }
-
-[^[:alnum:]_]typedef{WS}{ITYPE}{WS}{ID}{WS}?";" {
-
-  char *namestart;
-  size_t namelen;
-  char *typestart;
-  size_t typelen;
-
-  for (namestart = yytext + yyleng - 2; ISSPACE (*namestart); namestart--)
-    ;
-  for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++)
-    ;
-  namestart -= namelen - 1;
-  for (typestart = yytext + strlen (" typedef "); 
-       ISSPACE(*typestart);
-       typestart++)
-    ;
-  for (typelen = namestart - typestart;
-       ISSPACE (typestart[typelen-1]);
-       typelen--)
-    ;
-  typestart[typelen] = '\0';
-
-  do_typedef ((const char *) xmemdup (namestart, namelen, namelen+1),
-  	      create_scalar_type (typestart),
-	      &lexer_line);
-  update_lineno (yytext, yyleng);
+^struct/{EOID} {
+  BEGIN(in_struct);
+  return STRUCT;
 }
-
-[^[:alnum:]_]typedef{WS}{ID}{WS}{ID}{WS}"(" {
-  char *namestart;
-  size_t namelen;
-
-  for (namestart = yytext + yyleng - 2; ISSPACE (*namestart); namestart--)
-    ;
-  for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++)
-    ;
-  namestart -= namelen - 1;
-
-  do_scalar_typedef ((const char *) xmemdup (namestart, namelen, namelen+1),
-  		     &lexer_line);
-  update_lineno (yytext, yyleng);
+^union/{EOID} {
+  BEGIN(in_struct);
+  return UNION;
 }
-
-[^[:alnum:]_]typedef{WS}{ID}{WS}?"*"?{WS}?"("{WS}?"*"{WS}?{ID}{WS}?")"{WS}?"(" {
-  char *namestart;
-  size_t namelen;
-
-  for (namestart = yytext + yyleng - 2; !ISIDNUM (*namestart); namestart--)
-    ;
-  for (namelen = 1; ISIDNUM (namestart[-namelen]); namelen++)
-    ;
-  namestart -= namelen - 1;
-
-  do_scalar_typedef ((const char *) xmemdup (namestart, namelen, namelen+1),
-  		     &lexer_line);
-  update_lineno (yytext, yyleng);
+^extern/{EOID} {
+  BEGIN(in_struct);
+  return EXTERN;
 }
-
-[^[:alnum:]_](typedef{WS})?(struct|union){WS}{ID}{WS}/"GTY" {
-  char *tagstart;
-  size_t taglen;
-  int typedef_p;
-  int union_p;
-
-  typedef_p = yytext[1] == 't';
-  if (typedef_p)
-    for (tagstart = yytext + strlen (" typedef "); 
-	 ISSPACE(*tagstart);
-	 tagstart++)
-      ;
-  else
-    tagstart = yytext + 1;
-
-  union_p = tagstart[0] == 'u';
-  tagstart += strlen ("union ");
-  while (ISSPACE (*tagstart))
-    tagstart++;
-  for (taglen = 1; ISIDNUM (tagstart[taglen]); taglen++)
-    ;
-
-  yylval.s = (const char *) xmemdup (tagstart, taglen, taglen + 1);
-
+^static/{EOID} {
   BEGIN(in_struct);
-  update_lineno (yytext, yyleng);
-  return union_p ? (typedef_p ? ENT_TYPEDEF_UNION : ENT_UNION)
-                 : (typedef_p ? ENT_TYPEDEF_STRUCT : ENT_STRUCT);
+  return STATIC;
 }
 
-[^[:alnum:]_](extern|static){WS}/"GTY" {
+^DEF_VEC_[OP]/{EOID} {
   BEGIN(in_struct);
-  update_lineno (yytext, yyleng);
-  return ENT_EXTERNSTATIC;
+  return DEFVEC_OP;
+}
+^DEF_VEC_I/{EOID} {
+  BEGIN(in_struct);
+  return DEFVEC_I;
+}
+^DEF_VEC_ALLOC_[IOP]/{EOID} {
+  BEGIN(in_struct);
+  return DEFVEC_ALLOC;
 }
-
-^"DEF_VEC_"[IPO]{WS}?"("{WS}?{ID}{WS}?")" {
-  /* Definition of a generic VEC structure.  If the letter after
-     DEF_VEC_ is "I", the structure definition is slightly different
-     than if it is "P" or "O".  */
-
-  char *p = yytext + sizeof("DEF_VEC_") - 1;
-  char *q;
-  const char *type;
-  bool is_I = (*p == 'I');
-
-  /* Extract the argument to the macro.  */
-  p++;
-  while (!ISALNUM(*p) && *p != '_')
-    p++;
-  q = p;
-  while (ISALNUM(*q) || *q == '_')
-    ++;
-  type = xmemdup (p, q - p, q - p + 1);
-
-  note_def_vec (type, is_I, &lexer_line);
-  note_def_vec_alloc (type, "none", &lexer_line);
-}
-
-^"DEF_VEC_ALLOC_"[IPO]{WS}?"("{WS}?{ID}{WS}?","{WS}?{ID}{WS}?")" {
-  /* Definition of an allocation strategy for a VEC structure.  For
-     purposes of gengtype, this just declares a wrapper structure.  */
-
-  char *p = yytext + sizeof("DEF_VEC_ALLOC_I") - 1;
-  char *q;
-  char *type, *astrat;
-
-  /* Extract the two arguments to the macro.  */
-  while (!ISALNUM(*p) && *p != '_')
-    p++;
-  q = p;
-  while (ISALNUM(*q) || *q == '_')
-    q++;
-  type = alloca (q - p + 1);
-  memcpy (type, p, q - p);
-  type[q - p] = '\0';
-  p = q;
-
-  while (!ISALNUM(*p) && *p != '_')
-    p++;
-  q = p;
-  while (ISALNUM(*q) || *q == '_')
-    q++;
-  astrat = alloca (q - p + 1);
-  memcpy (astrat, p, q - p);
-  astrat[q - p] = '\0';
-
-  note_def_vec_alloc (type, astrat, &lexer_line);
 }
 
 <in_struct>{
@@ -245,63 +106,57 @@
 
 {WS}				{ update_lineno (yytext, yyleng); }
 
-"const"/[^[:alnum:]_]		/* don't care */
-"GTY"/[^[:alnum:]_]		{ return GTY_TOKEN; }
-"VEC"/[^[:alnum:]_]		{ return VEC_TOKEN; }
-"union"/[^[:alnum:]_]		{ return UNION; }
-"struct"/[^[:alnum:]_]		{ return STRUCT; }
-"enum"/[^[:alnum:]_]		{ return ENUM; }
-"ptr_alias"/[^[:alnum:]_]	{ return ALIAS; }
-"nested_ptr"/[^[:alnum:]_]	{ return NESTED_PTR; }
+"const"/{EOID}			/* don't care */
+"GTY"/{EOID}			{ return GTY_TOKEN; }
+"VEC"/{EOID}			{ return VEC_TOKEN; }
+"union"/{EOID}			{ return UNION; }
+"struct"/{EOID}			{ return STRUCT; }
+"enum"/{EOID}			{ return ENUM; }
+"ptr_alias"/{EOID}	  	{ return PTR_ALIAS; }
+"nested_ptr"/{EOID}		{ return NESTED_PTR; }
 [0-9]+				{ return NUM; }
-"param"[0-9]*"_is"/[^[:alnum:]_]		{
-  yylval.s = (const char *) xmemdup (yytext, yyleng, yyleng+1);
+"param"[0-9]*"_is"/{EOID}		{
+  *yylval = xmemdup (yytext, yyleng, yyleng+1);
   return PARAM_IS;
 }
 
-{IWORD}({WS}{IWORD})*/[^[:alnum:]_]		|
+{IWORD}({WS}{IWORD})*/{EOID}		|
 "ENUM_BITFIELD"{WS}?"("{WS}?{ID}{WS}?")"	{
   size_t len;
 
   for (len = yyleng; ISSPACE (yytext[len-1]); len--)
     ;
 
-  yylval.s = (const char *) xmemdup (yytext, len, len+1);
+  *yylval = xmemdup (yytext, len, len+1);
   update_lineno (yytext, yyleng);
   return SCALAR;
 }
 
 
-{ID}/[^[:alnum:]_]		{
-  yylval.s = (const char *) xmemdup (yytext, yyleng, yyleng+1);
+{ID}/{EOID}			{
+  *yylval = xmemdup (yytext, yyleng, yyleng+1);
   return ID;
 }
 
 \"([^"\\]|\\.)*\"		{
-  yylval.s = (const char *) xmemdup (yytext+1, yyleng-2, yyleng-1);
+  *yylval = xmemdup (yytext+1, yyleng-2, yyleng-1);
   return STRING;
 }
+  /* This "terminal" avoids having to parse integer constant expressions.  */
 "["[^\[\]]*"]"			{
-  yylval.s = (const char *) xmemdup (yytext+1, yyleng-2, yyleng-1);
+  *yylval = xmemdup (yytext+1, yyleng-2, yyleng-1);
   return ARRAY;
 }
 "'"("\\".|[^\\])"'"		{
-  yylval.s = (const char *) xmemdup (yytext+1, yyleng-2, yyleng);
+  *yylval = xmemdup (yytext+1, yyleng-2, yyleng);
   return CHAR;
 }
 
-[(){},*:<>]			{ return yytext[0]; }
-
-[;=]				{
-  if (lexer_toplevel_done)
-    {
-      BEGIN(INITIAL);
-      lexer_toplevel_done = 0;
-    }
-  return yytext[0];
-}
+"..."				{ return ELLIPSIS; }
+[(){},*:<>;=%|-]		{ return yytext[0]; }
 
-"#define"[^\n]*\n		{lexer_line.line++;}
+   /* ignore pp-directives */
+^{HWS}"#"{HWS}[a-z_]+[^\n]*\n   {lexer_line.line++;}
 
 .				{
   error_at_line (&lexer_line, "unexpected character `%s'", yytext);
@@ -339,23 +194,20 @@
 %%
 
 void
-yyerror (const char *s)
-{
-  error_at_line (&lexer_line, s);
-}
-
-void
-parse_file (const char *fname)
+yybegin (const char *fname)
 {
   yyin = fopen (fname, "r");
-  lexer_line.file = fname;
-  lexer_line.line = 1;
   if (yyin == NULL)
     {
       perror (fname);
       exit (1);
     }
-  if (yyparse() != 0)
-    exit (1);
+  lexer_line.file = fname;
+  lexer_line.line = 1;
+}
+
+void
+yyend (void)
+{
   fclose (yyin);
 }
Index: S-vn-gtsmall/gcc/gengtype.c
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype.c	2007-03-26 14:05:45.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype.c	2007-03-26 14:08:04.000000000 -0700
@@ -155,7 +155,7 @@
 
 
 /* Nonzero iff an error has occurred.  */
-static int hit_error = 0;
+bool hit_error = false;
 
 static void gen_rtx_next (void);
 static void write_rtx_next (void);
@@ -174,13 +174,13 @@
   fprintf (stderr, "%s:%d: ", pos->file, pos->line);
   vfprintf (stderr, msg, ap);
   fputc ('\n', stderr);
-  hit_error = 1;
+  hit_error = true;
 
   va_end (ap);
 }
 
 /* asprintf, but produces fatal message on out-of-memory.  */
-static char * ATTRIBUTE_PRINTF_1
+char *
 xasprintf (const char *format, ...)
 {
   int n;
@@ -202,6 +202,11 @@
 static const char **gt_files;
 static size_t num_gt_files;
 
+/* 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;
 static size_t num_lang_dirs;
@@ -225,11 +230,18 @@
 static lang_bitmap
 get_lang_bitmap (const char *gtfile)
 {
-  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;
+
+  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
@@ -509,6 +521,18 @@
 {
   pair_p p;
 
+  /* temporary kludge - gengtype doesn't handle conditionals or macros.
+     Ignore any attempt to typedef CUMULATIVE_ARGS, location_t,
+     expanded_location, or source_locus, unless it is coming from
+     this file (main() sets them up with safe dummy definitions).  */
+  if ((!strcmp (s, "CUMULATIVE_ARGS")
+       || !strcmp (s, "location_t")
+       || !strcmp (s, "source_locus")
+       || !strcmp (s, "source_location")
+       || !strcmp (s, "expanded_location"))
+      && pos->file != this_file)
+    return;
+
   for (p = typedefs; p != NULL; p = p->next)
     if (strcmp (p->name, s) == 0)
       {
@@ -562,6 +586,13 @@
   type_p s = NULL;
   lang_bitmap bitmap = get_lang_bitmap (pos->file);
 
+  /* 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)
+    return find_structure (name, 0);
+
   for (si = structures; si != NULL; si = si->next)
     if (strcmp (name, si->u.s.tag) == 0
 	&& UNION_P (si) == isunion)
@@ -610,7 +641,8 @@
   if (s->u.s.line.file != NULL
       || (s->u.s.lang_struct && (s->u.s.lang_struct->u.s.bitmap & bitmap)))
     {
-      error_at_line (pos, "duplicate structure definition");
+      error_at_line (pos, "duplicate definition of '%s %s'",
+		     isunion ? "union" : "struct", s->u.s.tag);
       error_at_line (&s->u.s.line, "previous definition here");
     }
 
@@ -623,7 +655,22 @@
   if (s->u.s.lang_struct)
     s->u.s.lang_struct->u.s.bitmap |= bitmap;
 
-  return s;
+  /* 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)
+    {
+      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;
+	  }
+    }
+
+    return s;
 }
 
 /* Return the previously-defined structure with tag NAME (or a union
@@ -788,7 +835,7 @@
 /* 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, __FILE__, __LINE__)
+    create_field_all(next,type,name, 0, this_file, __LINE__)
 
 /* Like create_field, but the field is only valid when condition COND
    is true.  */
@@ -814,11 +861,26 @@
      tag that specifies the condition under which the field is valid.  */
   return create_field_all (next, union_type, name,
 			   create_option (0, "desc", cond),
-			   __FILE__, line);
+			   this_file, line);
 }
 #define create_optional_field(next,type,name,cond)	\
        create_optional_field_(next,type,name,cond,__LINE__)
 
+/* Reverse a linked list of 'struct pair's in place.  */
+pair_p
+nreverse_pairs (pair_p list)
+{
+  pair_p prev = 0, p, next;
+  for (p = list; p; p = next)
+    {
+      next = p->next;
+      p->next = prev;
+      prev = p;
+    }
+  return prev;
+}
+
+
 /* We don't care how long a CONST_DOUBLE is.  */
 #define CONST_DOUBLE_FORMAT "ww"
 /* We don't want to see codes that are only for generator files.  */
@@ -3420,12 +3482,42 @@
   do_typedef (astratname, new_structure (astratname, 0, pos, field, 0), pos);
 }
 
+/* Yet more temporary kludge since gengtype doesn't understand conditionals.
+   This must be kept in sync with input.h.  */
+static void
+define_location_structures (void)
+{
+  pair_p fields;
+  type_p locs;
+  static struct fileloc pos = { this_file, __LINE__ };
+  do_scalar_typedef ("source_location", &pos);
+
+#ifdef USE_MAPPED_LOCATION
+    fields = create_field (0, &scalar_nonchar, "column");
+    fields = create_field (fields, &scalar_nonchar, "line");
+    fields = create_field (fields, &string_type, "file");
+    locs = new_structure ("anon:expanded_location", 0, &pos, fields, 0);
+
+    do_typedef ("expanded_location", locs, &pos);
+    do_scalar_typedef ("location_t", &pos);
+    do_scalar_typedef ("source_locus", &pos);
+#else
+    fields = create_field (0, &scalar_nonchar, "line");
+    fields = create_field (fields, &string_type, "file");
+    locs = new_structure ("location_s", 0, &pos, fields, 0);
+
+    do_typedef ("expanded_location", locs, &pos);
+    do_typedef ("location_t", locs, &pos);
+    do_typedef ("source_locus", create_pointer (locs), &pos);
+#endif
+}
+
 
 int
 main (int argc, char **argv)
 {
   size_t i;
-  static struct fileloc pos = { __FILE__, __LINE__ };
+  static struct fileloc pos = { this_file, 0 };
 
   /* fatal uses this */
   progname = "gengtype";
@@ -3444,34 +3536,23 @@
   scalar_nonchar.u.scalar_is_char = false;
   gen_rtx_next ();
 
-  do_scalar_typedef ("CUMULATIVE_ARGS", &pos);
-  do_scalar_typedef ("REAL_VALUE_TYPE", &pos);
-  do_scalar_typedef ("double_int", &pos);
-  do_scalar_typedef ("uint8", &pos);
-  do_scalar_typedef ("jword", &pos);
-  do_scalar_typedef ("JCF_u2", &pos);
-#ifdef USE_MAPPED_LOCATION
-  do_scalar_typedef ("location_t", &pos);
-  do_scalar_typedef ("source_locus", &pos);
-#endif
-  do_scalar_typedef ("void", &pos);
-
+  /* These types are set up with #define or else outside of where
+     we can see them.  */
+  pos.line = __LINE__ + 1;
+  do_scalar_typedef ("CUMULATIVE_ARGS", &pos); pos.line++;
+  do_scalar_typedef ("REAL_VALUE_TYPE", &pos); pos.line++;
+  do_scalar_typedef ("double_int", &pos); pos.line++;
+  do_scalar_typedef ("uint8", &pos); pos.line++;
+  do_scalar_typedef ("jword", &pos); pos.line++;
+  do_scalar_typedef ("JCF_u2", &pos); pos.line++;
+  do_scalar_typedef ("void", &pos); pos.line++;
   do_typedef ("PTR", create_pointer (resolve_typedef ("void", &pos)), &pos);
-
-  do_typedef ("HARD_REG_SET", create_array (&scalar_nonchar, "2"), &pos);
+  define_location_structures ();
 
   for (i = 0; i < num_gt_files; i++)
-    {
-      parse_file (gt_files[i]);
-#ifndef USE_MAPPED_LOCATION
-      /* temporary kludge - gengtype doesn't handle conditionals.
-	 Manually add source_locus *after* we've processed input.h.  */
-      if (i == 0)
-	do_typedef ("source_locus", create_pointer (resolve_typedef ("location_t", &pos)), &pos);
-#endif
-    }
+    parse_file (gt_files[i]);
 
-  if (hit_error != 0)
+  if (hit_error)
     return 1;
 
   set_gc_used (variables);
@@ -3485,5 +3566,7 @@
   write_rtx_next ();
   close_output_files ();
 
-  return (hit_error != 0);
+  if (hit_error)
+    return 1;
+  return 0;
 }
Index: S-vn-gtsmall/gcc/gengtype.h
===================================================================
--- S-vn-gtsmall.orig/gcc/gengtype.h	2007-03-26 14:01:52.000000000 -0700
+++ S-vn-gtsmall/gcc/gengtype.h	2007-03-26 14:08:04.000000000 -0700
@@ -41,6 +41,9 @@
 extern void error_at_line 
   (struct fileloc *pos, const char *msg, ...) ATTRIBUTE_PRINTF_2;
 
+/* Like asprintf, but calls fatal() on out of memory.  */
+extern char *xasprintf(const char *, ...) ATTRIBUTE_PRINTF_1;
+
 /* Constructor routines for types.  */
 extern void do_typedef (const char *s, type_p t, struct fileloc *pos);
 extern void do_scalar_typedef (const char *s, struct fileloc *pos);
@@ -57,6 +60,7 @@
 					   const char *from, const char *to);
 extern pair_p create_field_at (pair_p next, type_p type, const char *name,
 			       options_p opt, struct fileloc *pos);
+extern pair_p nreverse_pairs (pair_p list);
 extern type_p adjust_field_type (type_p, options_p);
 extern void note_variable (const char *s, type_p t, options_p o,
 			   struct fileloc *pos);
@@ -65,10 +69,45 @@
 extern void note_def_vec_alloc (const char *type, const char *astrat,
 				struct fileloc *pos);
 
-/* Lexer and parser routines, most automatically generated.  */
-extern int yylex (void);
-extern void yyerror (const char *);
-extern int yyparse (void);
+/* Lexer and parser routines.  */
+extern int yylex (const char **yylval);
+extern void yybegin (const char *fname);
+extern void yyend (void);
 extern void parse_file (const char *name);
+extern bool hit_error;
+
+/* Token codes.  */
+enum {
+  EOF_TOKEN = 0,
+
+  /* Per standard convention, codes in the range (0, UCHAR_MAX]
+     represent single characters with those character codes.  */
+
+  CHAR_TOKEN_OFFSET = UCHAR_MAX + 1,
+  GTY_TOKEN = CHAR_TOKEN_OFFSET,
+  TYPEDEF,
+  EXTERN,
+  STATIC,
+  UNION,
+  STRUCT,
+  ENUM,
+  VEC_TOKEN,
+  DEFVEC_OP,
+  DEFVEC_I,
+  DEFVEC_ALLOC,
+  ELLIPSIS,
+  PTR_ALIAS,
+  NESTED_PTR,
+  PARAM_IS,
+  NUM,
+  SCALAR,
+  ID,
+  STRING,
+  CHAR,
+  ARRAY,
 
+  /* print_token assumes that any token >= FIRST_TOKEN_WITH_VALUE may have
+     a meaningful value to be printed.  */
+  FIRST_TOKEN_WITH_VALUE = PARAM_IS
+};
 #endif
Index: S-vn-gtsmall/gcc/input.h
===================================================================
--- S-vn-gtsmall.orig/gcc/input.h	2007-03-26 13:32:50.000000000 -0700
+++ S-vn-gtsmall/gcc/input.h	2007-03-26 14:08:04.000000000 -0700
@@ -28,6 +28,9 @@
 /* The location for declarations in "<built-in>" */
 #define BUILTINS_LOCATION ((source_location) 2)
 
+/* Note: if any of the types defined inside this #ifdef are changed,
+   gengtype.c:define_location_structures must be updated to match.  */
+
 #ifdef USE_MAPPED_LOCATION
 
 typedef struct
Index: S-vn-gtsmall/gcc/doc/install.texi
===================================================================
--- S-vn-gtsmall.orig/gcc/doc/install.texi	2007-03-26 14:13:02.000000000 -0700
+++ S-vn-gtsmall/gcc/doc/install.texi	2007-03-26 14:15:35.000000000 -0700
@@ -375,14 +375,14 @@
 @file{Makefile.tpl} and @file{Makefile.def}.
 
 @item GNU Bison version 1.28 (or later)
-Berkeley @command{yacc} (@command{byacc}) is also reported to work other
-than for GCJ.
 
-Necessary when modifying @file{*.y} files.
+Necessary when modifying @file{*.y} files.  Necessary to build the
+@code{treelang} front end (which is not enabled by default) from a
+checkout of the SVN repository; the generated files are not in the
+repository.  They are included in releases.
 
-Necessary to build GCC during development because the generated output
-files are not included in the SVN repository.  They are included in
-releases.
+Berkeley @command{yacc} (@command{byacc}) has been reported to work
+as well.
 
 @item Flex version 2.5.4 (or later)
 
@@ -1650,10 +1650,18 @@
 
 The solution is not to use such a directory for building GCC@.
 
-When building from SVN or snapshots, or if you modify parser sources,
-you need the Bison parser generator installed.  If you do not modify
-parser sources, releases contain the Bison-generated files and you do
-not need Bison installed to build them.
+When building from SVN or snapshots and enabling the @code{treelang}
+front end, or if you modify @file{*.y} files, you need the Bison parser
+generator installed.  If you do not modify @file{*.y} files, releases
+contain the Bison-generated files and you do not need Bison installed
+to build them.  Note that most front ends now use hand-written parsers,
+which can be modified with no need for Bison.
+
+Similarly, when building from SVN or snapshots, or if you modify
+@file{*.l} files, you need the Flex lexical analyzer generator installed.
+There is still one Flex-based lexical analyzer (part of the build
+machinery, not of GCC itself) that is used even if you only build the
+C front end.
 
 When building from SVN or snapshots, or if you modify Texinfo
 documentation, you need version 4.4 or later of Texinfo installed if you

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]