]> git.saurik.com Git - bison.git/blobdiff - src/output.c
* src/lex.c (percent_table): Add tok_define.
[bison.git] / src / output.c
index a426ad8f94f5bcddb5706296a49777c1f07103a6..d5c3b990517640fd95411d199a6a03706e1534fd 100644 (file)
@@ -1,5 +1,5 @@
 /* Output the generated parsing program for bison,
 /* Output the generated parsing program for bison,
-   Copyright (C) 1984, 1986, 1989, 1992, 2000 Free Software Foundation, Inc.
+   Copyright 1984, 1986, 1989, 1992, 2000, 2001 Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
 
    This file is part of Bison, the GNU Compiler Compiler.
 
@@ -91,6 +91,8 @@
 */
 
 #include "system.h"
 */
 
 #include "system.h"
+#include "obstack.h"
+#include "quotearg.h"
 #include "getargs.h"
 #include "xalloc.h"
 #include "files.h"
 #include "getargs.h"
 #include "xalloc.h"
 #include "files.h"
@@ -125,24 +127,30 @@ static int high;
 
 
 static inline void
 
 
 static inline void
-output_short_table (FILE *out,
-                   const char *table_name,
-                   short *short_table,
-                   short first_value,
-                   short begin, short end)
+output_short_or_char_table (struct obstack *oout,
+                           const char *comment,
+                           const char *type,
+                           const char *table_name,
+                           short *short_table,
+                           short first_value,
+                           short begin, short end)
 {
   int i, j;
 
 {
   int i, j;
 
-  fprintf (out, "static const short %s[] = {%6d", table_name, first_value);
+  if (comment)
+    obstack_fgrow1 (oout, "/* %s. */\n", comment);
+
+  obstack_fgrow3 (oout, "static const %s %s[] =\n{\n  %6d",
+                 type, table_name, first_value);
 
 
-  j = 10;
+  j = 1;
   for (i = begin; i < end; i++)
     {
   for (i = begin; i < end; i++)
     {
-      putc (',', out);
+      obstack_1grow (oout, ',');
 
       if (j >= 10)
        {
 
       if (j >= 10)
        {
-         putc ('\n', out);
+         obstack_sgrow (oout, "\n  ");
          j = 1;
        }
       else
          j = 1;
        }
       else
@@ -150,10 +158,23 @@ output_short_table (FILE *out,
          j++;
        }
 
          j++;
        }
 
-      fprintf (out, "%6d", short_table[i]);
+      obstack_fgrow1 (oout, "%6d", short_table[i]);
     }
 
     }
 
-  fprintf (out, "\n};\n");
+  obstack_sgrow (oout, "\n};\n");
+}
+
+
+static inline void
+output_short_table (struct obstack *oout,
+                   const char *comment,
+                   const char *table_name,
+                   short *short_table,
+                   short first_value,
+                   short begin, short end)
+{
+  output_short_or_char_table (oout, comment, "short", table_name, short_table,
+                             first_value, begin, end);
 }
 
 
 }
 
 
@@ -162,9 +183,11 @@ output_short_table (FILE *out,
 | certain files.                                                |
 `--------------------------------------------------------------*/
 
 | certain files.                                                |
 `--------------------------------------------------------------*/
 
+/* Don't put the `%s' insides quotes, since it quotearg puts them. */
+
 #define        GUARDSTR        \
 "\n\
 #define        GUARDSTR        \
 "\n\
-#include \"%s\"\n\
+#include %s\n\
 extern int yyerror;\n\
 extern int yycost;\n\
 extern char * yymsg;\n\
 extern int yyerror;\n\
 extern int yycost;\n\
 extern char * yymsg;\n\
@@ -183,7 +206,7 @@ register YYLTYPE *yylsp;\n\
 
 #define        ACTSTR          \
 "\n\
 
 #define        ACTSTR          \
 "\n\
-#include \"%s\"\n\
+#include %s\n\
 extern YYSTYPE yyval;\n\
 extern int yychar;\n\
 \n\
 extern YYSTYPE yyval;\n\
 extern int yychar;\n\
 \n\
@@ -200,28 +223,44 @@ register YYLTYPE *yylsp;\n\
 void
 output_headers (void)
 {
 void
 output_headers (void)
 {
+  char *attrsfile_quoted = 0;
+
   if (semantic_parser)
   if (semantic_parser)
-    fprintf (fguard, GUARDSTR, attrsfile);
+    {
+      /* FIXME: This is *buggy*.  ATTRSFILE is not computed yet, since
+        we are waiting for the full input file to have been read to
+        be sure of the output file name.  So basically, here, a SEGV
+        is guaranteed.  OTOH, currently semantic parsers are not
+        supported.  */
+      attrsfile_quoted = quotearg_style (c_quoting_style, attrsfile);
+      obstack_fgrow1 (&guard_obstack, GUARDSTR, attrsfile_quoted);
+    }
 
   if (no_parser_flag)
     return;
 
 
   if (no_parser_flag)
     return;
 
-  fprintf (faction, (semantic_parser ? ACTSTR : ACTSTR_SIMPLE), attrsfile);
-/*  if (semantic_parser)       JF moved this below
-    fprintf(ftable, "#include \"%s\"\n", attrsfile);
-  fprintf(ftable, "#include <stdio.h>\n\n");
-*/
+  if (semantic_parser)
+    obstack_fgrow1 (&action_obstack, ACTSTR, attrsfile_quoted);
+  else
+    obstack_sgrow (&action_obstack, ACTSTR_SIMPLE);
 
   /* Rename certain symbols if -p was specified.  */
   if (spec_name_prefix)
     {
 
   /* Rename certain symbols if -p was specified.  */
   if (spec_name_prefix)
     {
-      fprintf (ftable, "#define yyparse %sparse\n", spec_name_prefix);
-      fprintf (ftable, "#define yylex %slex\n", spec_name_prefix);
-      fprintf (ftable, "#define yyerror %serror\n", spec_name_prefix);
-      fprintf (ftable, "#define yylval %slval\n", spec_name_prefix);
-      fprintf (ftable, "#define yychar %schar\n", spec_name_prefix);
-      fprintf (ftable, "#define yydebug %sdebug\n", spec_name_prefix);
-      fprintf (ftable, "#define yynerrs %snerrs\n", spec_name_prefix);
+      obstack_fgrow1 (&table_obstack,
+                     "#define yyparse %sparse\n", spec_name_prefix);
+      obstack_fgrow1 (&table_obstack,
+                     "#define yylex %slex\n", spec_name_prefix);
+      obstack_fgrow1 (&table_obstack,
+                     "#define yyerror %serror\n", spec_name_prefix);
+      obstack_fgrow1 (&table_obstack,
+                     "#define yylval %slval\n", spec_name_prefix);
+      obstack_fgrow1 (&table_obstack,
+                     "#define yychar %schar\n", spec_name_prefix);
+      obstack_fgrow1 (&table_obstack,
+                     "#define yydebug %sdebug\n", spec_name_prefix);
+      obstack_fgrow1 (&table_obstack,
+                     "#define yynerrs %snerrs\n", spec_name_prefix);
     }
 }
 
     }
 }
 
@@ -234,16 +273,17 @@ void
 output_trailers (void)
 {
   if (semantic_parser)
 output_trailers (void)
 {
   if (semantic_parser)
-    fprintf (fguard, "\n    }\n}\n");
+    obstack_sgrow (&guard_obstack, "\n    }\n}\n");
 
 
-  fprintf (faction, "\n");
+  obstack_1grow (&action_obstack, '\n');
 
   if (no_parser_flag)
     return;
 
   if (semantic_parser)
 
   if (no_parser_flag)
     return;
 
   if (semantic_parser)
-    fprintf (faction, "    }\n");
-  fprintf (faction, "}\n");
+    obstack_sgrow (&action_obstack, "    }\n");
+
+  obstack_sgrow (&action_obstack, "}\n");
 }
 
 
 }
 
 
@@ -251,43 +291,28 @@ output_trailers (void)
 static void
 output_token_translations (void)
 {
 static void
 output_token_translations (void)
 {
-  int i, j;
-/*   short *sp; JF unused */
+  obstack_sgrow (&table_obstack, "\
+\n\
+/* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */\n");
 
   if (translations)
     {
 
   if (translations)
     {
-      fprintf (ftable,
-              "\n#define YYTRANSLATE(x) ((unsigned)(x) <= %d ? yytranslate[x] : %d)\n",
+      obstack_fgrow2 (&table_obstack,
+      "#define YYTRANSLATE(x) ((unsigned)(x) <= %d ? yytranslate[x] : %d)\
+\n\
+\n",
               max_user_token_number, nsyms);
 
               max_user_token_number, nsyms);
 
-      if (ntokens < 127)       /* play it very safe; check maximum element value.  */
-       fprintf (ftable, "\nstatic const char yytranslate[] = {     0");
-      else
-       fprintf (ftable, "\nstatic const short yytranslate[] = {     0");
-
-      j = 10;
-      for (i = 1; i <= max_user_token_number; i++)
-       {
-         putc (',', ftable);
-
-         if (j >= 10)
-           {
-             putc ('\n', ftable);
-             j = 1;
-           }
-         else
-           {
-             j++;
-           }
-
-         fprintf (ftable, "%6d", token_translations[i]);
-       }
-
-      fprintf (ftable, "\n};\n");
+      output_short_or_char_table (&table_obstack,
+            "YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX",
+                   ntokens < 127 ? "char" : "short",
+                   "yytranslate", token_translations,
+                   0, 1, max_user_token_number + 1);
     }
   else
     {
     }
   else
     {
-      fprintf (ftable, "\n#define YYTRANSLATE(x) (x)\n");
+      obstack_sgrow (&table_obstack,
+                          "\n#define YYTRANSLATE(x) (x)\n");
     }
 }
 
     }
 }
 
@@ -295,52 +320,41 @@ output_token_translations (void)
 static void
 output_gram (void)
 {
 static void
 output_gram (void)
 {
-  int j;
-  short *sp;
-
   /* With the ordinary parser,
      yyprhs and yyrhs are needed only for yydebug. */
   /* With the no_parser option, all tables are generated */
   if (!semantic_parser && !no_parser_flag)
   /* With the ordinary parser,
      yyprhs and yyrhs are needed only for yydebug. */
   /* With the no_parser option, all tables are generated */
   if (!semantic_parser && !no_parser_flag)
-    fprintf (ftable, "\n#if YYDEBUG != 0\n");
+    obstack_sgrow (&table_obstack, "\n#if YYDEBUG != 0\n");
 
 
-  output_short_table (ftable, "yyprhs", rrhs,
+  output_short_table (&table_obstack, NULL, "yyprhs", rrhs,
                      0, 1, nrules + 1);
 
                      0, 1, nrules + 1);
 
-  fprintf (ftable, "\nstatic const short yyrhs[] = {%6d", ritem[0]);
+  {
+    size_t yyrhs_size = 1;
+    short *yyrhs, *sp;
+    int i;
 
 
-  j = 10;
-  for (sp = ritem + 1; *sp; sp++)
-    {
-      putc (',', ftable);
-
-      if (j >= 10)
-       {
-         putc ('\n', ftable);
-         j = 1;
-       }
-      else
-       {
-         j++;
-       }
+    for (sp = ritem + 1; *sp; sp++)
+      ++yyrhs_size;
+    yyrhs = XMALLOC (short, yyrhs_size);
 
 
-      if (*sp > 0)
-       fprintf (ftable, "%6d", *sp);
-      else
-       fprintf (ftable, "     0");
-    }
+    for (sp = ritem + 1, i = 1; *sp; ++sp, ++i)
+      yyrhs[i] = *sp > 0 ? *sp : 0;
 
 
-  fprintf (ftable, "\n};\n");
+    output_short_table (&table_obstack, NULL, "yyrhs", yyrhs,
+                       ritem[0], 1, yyrhs_size);
+    XFREE (yyrhs);
+  }
 
   if (!semantic_parser && !no_parser_flag)
 
   if (!semantic_parser && !no_parser_flag)
-    fprintf (ftable, "\n#endif\n");
+    obstack_sgrow (&table_obstack, "\n#endif\n");
 }
 
 
 static void
 output_stos (void)
 {
 }
 
 
 static void
 output_stos (void)
 {
-  output_short_table (ftable, "yystos", accessing_symbol,
+  output_short_table (&table_obstack, NULL, "yystos", accessing_symbol,
                      0, 1, nstates);
 }
 
                      0, 1, nstates);
 }
 
@@ -350,139 +364,119 @@ output_rule_data (void)
 {
   int i;
   int j;
 {
   int i;
   int j;
+  short *short_tab = NULL;
 
 
-  fputs ("\n\
-#if YYDEBUG != 0\n\
-/* YYRLINE[yyn]: source line where rule number YYN was defined. */\n",
-        ftable);
+  obstack_sgrow (&table_obstack, "\n\
+#if YYDEBUG != 0\n");
 
 
-  output_short_table (ftable, "yyrline", rline,
+  output_short_table (&table_obstack,
+           "YYRLINE[YYN] -- source line where rule number YYN was defined",
+                     "yyrline", rline,
                      0, 1, nrules + 1);
 
                      0, 1, nrules + 1);
 
-  fputs ("#endif\n\n", ftable);
+  obstack_sgrow (&table_obstack, "#endif\n\n");
 
   if (token_table_flag || no_parser_flag)
     {
 
   if (token_table_flag || no_parser_flag)
     {
-      fprintf (ftable, "#define YYNTOKENS %d\n", ntokens);
-      fprintf (ftable, "#define YYNNTS %d\n", nvars);
-      fprintf (ftable, "#define YYNRULES %d\n", nrules);
-      fprintf (ftable, "#define YYNSTATES %d\n", nstates);
-      fprintf (ftable, "#define YYMAXUTOK %d\n\n", max_user_token_number);
+      obstack_fgrow1 (&table_obstack, "#define YYNTOKENS %d\n", ntokens);
+      obstack_fgrow1 (&table_obstack, "#define YYNNTS %d\n", nvars);
+      obstack_fgrow1 (&table_obstack, "#define YYNRULES %d\n", nrules);
+      obstack_fgrow1 (&table_obstack, "#define YYNSTATES %d\n", nstates);
+      obstack_fgrow1 (&table_obstack, "#define YYMAXUTOK %d\n\n",
+                     max_user_token_number);
     }
 
     }
 
-  if (!token_table_flag && !no_parser_flag)
-    fprintf (ftable, "\n#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)\n\n");
-
   /* Output the table of symbol names.  */
   /* Output the table of symbol names.  */
-
-  fprintf (ftable,
-          "static const char * const yytname[] = {   \"%s\"", tags[0]);
-
-  j = strlen (tags[0]) + 44;
-  for (i = 1; i < nsyms; i++)
+  if (!token_table_flag && !no_parser_flag)
+    obstack_sgrow (&table_obstack,
+                        "\n#if YYDEBUG != 0 || defined YYERROR_VERBOSE\n\n");
+  obstack_sgrow (&table_obstack, "\
+/* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */\n");
+  obstack_sgrow (&table_obstack,
+          "static const char *const yytname[] =\n{\n  ");
+
+  j = 0;
+  for (i = 0; i < nsyms; i++)
     /* this used to be i<=nsyms, but that output a final "" symbol
        almost by accident */
     {
     /* this used to be i<=nsyms, but that output a final "" symbol
        almost by accident */
     {
+      /* Width of the next token, including the two quotes, the coma
+        and the space.  */
+      int strsize = 4;
       char *p;
       char *p;
-      putc (',', ftable);
-      j++;
 
 
-      if (j > 75)
+      for (p = tags[i]; p && *p; p++)
+       if (*p == '"' || *p == '\\' || *p == '\n' || *p == '\t'
+           || *p == '\b')
+         strsize += 2;
+       else if (*p < 040 || *p >= 0177)
+         strsize += 4;
+       else
+         strsize++;
+
+      if (j + strsize > 75)
        {
        {
-         putc ('\n', ftable);
-         j = 0;
+         obstack_sgrow (&table_obstack, "\n  ");
+         j = 2;
        }
 
        }
 
-      putc ('\"', ftable);
-      j++;
-
+      obstack_1grow (&table_obstack, '\"');
       for (p = tags[i]; p && *p; p++)
        {
          if (*p == '"' || *p == '\\')
       for (p = tags[i]; p && *p; p++)
        {
          if (*p == '"' || *p == '\\')
-           {
-             fprintf (ftable, "\\%c", *p);
-             j += 2;
-           }
+           obstack_fgrow1 (&table_obstack, "\\%c", *p);
          else if (*p == '\n')
          else if (*p == '\n')
-           {
-             fprintf (ftable, "\\n");
-             j += 2;
-           }
+           obstack_sgrow (&table_obstack, "\\n");
          else if (*p == '\t')
          else if (*p == '\t')
-           {
-             fprintf (ftable, "\\t");
-             j += 2;
-           }
+           obstack_sgrow (&table_obstack, "\\t");
          else if (*p == '\b')
          else if (*p == '\b')
-           {
-             fprintf (ftable, "\\b");
-             j += 2;
-           }
+           obstack_sgrow (&table_obstack, "\\b");
          else if (*p < 040 || *p >= 0177)
          else if (*p < 040 || *p >= 0177)
-           {
-             fprintf (ftable, "\\%03o", *p);
-             j += 4;
-           }
+           obstack_fgrow1 (&table_obstack, "\\%03o", *p);
          else
          else
-           {
-             putc (*p, ftable);
-             j++;
-           }
+           obstack_1grow (&table_obstack, *p);
        }
 
        }
 
-      putc ('\"', ftable);
-      j++;
+      obstack_sgrow (&table_obstack, "\", ");
+      j += strsize;
     }
   /* add a NULL entry to list of tokens */
     }
   /* add a NULL entry to list of tokens */
-  fprintf (ftable, ", NULL\n};\n");
+  obstack_sgrow (&table_obstack, "NULL\n};\n");
 
   if (!token_table_flag && !no_parser_flag)
 
   if (!token_table_flag && !no_parser_flag)
-    fprintf (ftable, "#endif\n\n");
+    obstack_sgrow (&table_obstack, "#endif\n\n");
 
   /* Output YYTOKNUM. */
   if (token_table_flag)
     {
 
   /* Output YYTOKNUM. */
   if (token_table_flag)
     {
-      output_short_table (ftable, "yytoknum", user_toknums,
+      output_short_table (&table_obstack,
+                 "YYTOKNUM[YYLEX] -- Index in YYTNAME corresponding to YYLEX",
+                         "yytoknum", user_toknums,
                          0, 1, ntokens + 1);
     }
 
   /* Output YYR1. */
                          0, 1, ntokens + 1);
     }
 
   /* Output YYR1. */
-  fputs ("\
-/* YYR1[YYN]: Symbol number of symbol that rule YYN derives. */\n", ftable);
-
-  output_short_table (ftable, "yyr1", rlhs,
+  output_short_table (&table_obstack,
+             "YYR1[YYN] -- Symbol number of symbol that rule YYN derives",
+                     "yyr1", rlhs,
                      0, 1, nrules + 1);
   XFREE (rlhs + 1);
 
                      0, 1, nrules + 1);
   XFREE (rlhs + 1);
 
-  putc ('\n', ftable);
+  obstack_1grow (&table_obstack, '\n');
 
   /* Output YYR2. */
 
   /* Output YYR2. */
-  fputs ("\
-/* YYR2[YYN]: Number of symbols composing right hand side of rule YYN. */\n\
-static const short yyr2[] = {     0", ftable);
-  j = 10;
+  short_tab = XMALLOC (short, nrules + 1);
   for (i = 1; i < nrules; i++)
   for (i = 1; i < nrules; i++)
-    {
-      putc (',', ftable);
-
-      if (j >= 10)
-       {
-         putc ('\n', ftable);
-         j = 1;
-       }
-      else
-       {
-         j++;
-       }
-
-      fprintf (ftable, "%6d", rrhs[i + 1] - rrhs[i] - 1);
-    }
+    short_tab[i] = rrhs[i + 1] - rrhs[i] - 1;
+  short_tab[nrules] = nitems - rrhs[nrules] - 1;
+  output_short_table (&table_obstack,
+        "YYR2[YYN] -- Number of symbols composing right hand side of rule YYN",
+                     "yyr2", short_tab,
+                     0, 1, nrules + 1);
+  obstack_1grow (&table_obstack, '\n');
 
 
-  putc (',', ftable);
-  if (j >= 10)
-    putc ('\n', ftable);
+  XFREE (short_tab);
 
 
-  fprintf (ftable, "%6d\n};\n", nitems - rrhs[nrules] - 1);
   XFREE (rrhs + 1);
 }
 
   XFREE (rrhs + 1);
 }
 
@@ -490,9 +484,9 @@ static const short yyr2[] = {     0", ftable);
 static void
 output_defines (void)
 {
 static void
 output_defines (void)
 {
-  fprintf (ftable, "\n\n#define\tYYFINAL\t\t%d\n", final_state);
-  fprintf (ftable, "#define\tYYFLAG\t\t%d\n", MINSHORT);
-  fprintf (ftable, "#define\tYYNTBASE\t%d\n", ntokens);
+  obstack_fgrow1 (&table_obstack, "\n\n#define\tYYFINAL\t\t%d\n", final_state);
+  obstack_fgrow1 (&table_obstack, "#define\tYYFLAG\t\t%d\n", MINSHORT);
+  obstack_fgrow1 (&table_obstack, "#define\tYYNTBASE\t%d\n", ntokens);
 }
 
 
 }
 
 
@@ -738,8 +732,13 @@ token_actions (void)
     }
   XFREE (actrow);
 
     }
   XFREE (actrow);
 
-  output_short_table (ftable, "yydefact", yydefact,
+  output_short_table (&table_obstack,
+  "YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE\n\
+   doesn't specify something else to do.  Zero means the default is an\n\
+   error",
+                     "yydefact", yydefact,
                      yydefact[0], 1, nstates);
                      yydefact[0], 1, nstates);
+  obstack_1grow (&table_obstack, '\n');
   XFREE (yydefact);
 }
 
   XFREE (yydefact);
 }
 
@@ -779,19 +778,17 @@ static void
 save_column (int symbol, int default_state)
 {
   int i;
 save_column (int symbol, int default_state)
 {
   int i;
-  int m;
-  int n;
   short *sp;
   short *sp1;
   short *sp2;
   int count;
   int symno;
 
   short *sp;
   short *sp1;
   short *sp2;
   int count;
   int symno;
 
-  m = goto_map[symbol];
-  n = goto_map[symbol + 1];
+  short begin = goto_map[symbol];
+  short end = goto_map[symbol + 1];
 
   count = 0;
 
   count = 0;
-  for (i = m; i < n; i++)
+  for (i = begin; i < end; i++)
     {
       if (to_state[i] != default_state)
        count++;
     {
       if (to_state[i] != default_state)
        count++;
@@ -805,7 +802,7 @@ save_column (int symbol, int default_state)
   froms[symno] = sp1 = sp = XCALLOC (short, count);
   tos[symno] = sp2 = XCALLOC (short, count);
 
   froms[symno] = sp1 = sp = XCALLOC (short, count);
   tos[symno] = sp2 = XCALLOC (short, count);
 
-  for (i = m; i < n; i++)
+  for (i = begin; i < end; i++)
     {
       if (to_state[i] != default_state)
        {
     {
       if (to_state[i] != default_state)
        {
@@ -867,36 +864,23 @@ default_goto (int symbol)
 static void
 goto_actions (void)
 {
 static void
 goto_actions (void)
 {
-  int i, j, k;
+  int i;
 
 
+  short *yydefgoto = XMALLOC (short, nsyms - ntokens);
   state_count = XCALLOC (short, nstates);
 
   state_count = XCALLOC (short, nstates);
 
-  k = default_goto (ntokens);
-  fprintf (ftable, "\nstatic const short yydefgoto[] = {%6d", k);
-  save_column (ntokens, k);
-
-  j = 10;
-  for (i = ntokens + 1; i < nsyms; i++)
+  for (i = ntokens; i < nsyms; ++i)
     {
     {
-      putc (',', ftable);
-
-      if (j >= 10)
-       {
-         putc ('\n', ftable);
-         j = 1;
-       }
-      else
-       {
-         j++;
-       }
-
-      k = default_goto (i);
-      fprintf (ftable, "%6d", k);
-      save_column (i, k);
+      int default_state = default_goto (i);
+      save_column (i, default_state);
+      yydefgoto[i - ntokens] = default_state;
     }
 
     }
 
-  fprintf (ftable, "\n};\n");
+  output_short_table (&table_obstack, NULL, "yydefgoto", yydefgoto,
+                     yydefgoto[0], 1, nsyms - ntokens);
+
   XFREE (state_count);
   XFREE (state_count);
+  XFREE (yydefgoto);
 }
 
 
 }
 
 
@@ -1095,12 +1079,12 @@ pack_table (void)
 static void
 output_base (void)
 {
 static void
 output_base (void)
 {
-  output_short_table (ftable, "yypact", base,
+  output_short_table (&table_obstack, NULL, "yypact", base,
                      base[0], 1, nstates);
 
                      base[0], 1, nstates);
 
-  putc ('\n', ftable);
+  obstack_1grow (&table_obstack, '\n');
 
 
-  output_short_table (ftable, "yypgoto", base,
+  output_short_table (&table_obstack, NULL, "yypgoto", base,
                      base[nstates], nstates + 1, nvectors);
 
   XFREE (base);
                      base[nstates], nstates + 1, nvectors);
 
   XFREE (base);
@@ -1110,8 +1094,8 @@ output_base (void)
 static void
 output_table (void)
 {
 static void
 output_table (void)
 {
-  fprintf (ftable, "\n\n#define\tYYLAST\t\t%d\n\n\n", high);
-  output_short_table (ftable, "yytable", table,
+  obstack_fgrow1 (&table_obstack, "\n\n#define\tYYLAST\t\t%d\n\n\n", high);
+  output_short_table (&table_obstack, NULL, "yytable", table,
                      table[0], 1, high + 1);
   XFREE (table);
 }
                      table[0], 1, high + 1);
   XFREE (table);
 }
@@ -1120,7 +1104,7 @@ output_table (void)
 static void
 output_check (void)
 {
 static void
 output_check (void)
 {
-  output_short_table (ftable, "yycheck", check,
+  output_short_table (&table_obstack, NULL, "yycheck", check,
                      check[0], 1, high + 1);
   XFREE (check);
 }
                      check[0], 1, high + 1);
   XFREE (check);
 }
@@ -1153,100 +1137,147 @@ output_actions (void)
 
   sort_actions ();
   pack_table ();
 
   sort_actions ();
   pack_table ();
-  putc ('\n', ftable);
+  obstack_1grow (&table_obstack, '\n');
   output_base ();
   output_table ();
   output_base ();
   output_table ();
-  putc ('\n', ftable);
+  obstack_1grow (&table_obstack, '\n');
   output_check ();
 }
 
   output_check ();
 }
 
-/* copy the parser code into the ftable file at the end.  */
+/*------------------------------------------.
+| Copy the parser code into TABLE_OBSTACK.  |
+`------------------------------------------*/
 
 static void
 output_parser (void)
 {
   int c;
 
 static void
 output_parser (void)
 {
   int c;
-  static int number_of_dollar_signs = 0;
-#ifdef DONTDEF
-  FILE *fpars;
-#else
-#define fpars fparser
-#endif
+  FILE *fskel;
+  size_t line;
+  int actions_dumped = 0;
 
   if (pure_parser)
 
   if (pure_parser)
-    fprintf (ftable, "#define YYPURE 1\n\n");
-
-#ifdef DONTDEF
-  /* JF no longer needed 'cuz open_extra_files changes the currently
-     open parser from bison.simple to bison.hairy */
-  if (semantic_parser)
-    fpars = fparser;
-  else
-    fpars = fparser1;
-#endif
+    obstack_sgrow (&table_obstack, "#define YYPURE 1\n\n");
 
   /* Loop over lines in the standard parser file.  */
 
   /* Loop over lines in the standard parser file.  */
+  if (!skeleton)
+    {
+      if (semantic_parser)
+       skeleton = skeleton_find ("BISON_HAIRY", BISON_HAIRY);
+      else
+       skeleton = skeleton_find ("BISON_SIMPLE", BISON_SIMPLE);
+    }
+  fskel = xfopen (skeleton, "r");
+
+  /* Set LINE to 2, not 1: `#line LINENUM' -- Here LINENUM is a
+     decimal integer constant.  This specifies that the line number of
+     the *following* line of input, in its original source file, was
+     LINENUM.  */
+  line = 2;
 
   while (1)
     {
 
   while (1)
     {
-      int write_line = 1;
+      enum line_type_e
+       {
+         regular_line,
+         sync_line,    /* #line. */
+         actions_line  /* %% actions. */
+       };
+      enum line_type_e line_type = regular_line;
 
 
-      c = getc (fpars);
+      c = getc (fskel);
 
 
-      /* See if the line starts with `#line.
-         If so, set write_line to 0.  */
-      if (no_lines_flag)
-       if (c == '#')
-         {
-           c = getc (fpars);
-           if (c == 'l')
-             {
-               c = getc (fpars);
-               if (c == 'i')
-                 {
-                   c = getc (fpars);
-                   if (c == 'n')
-                     {
-                       c = getc (fpars);
-                       if (c == 'e')
-                         write_line = 0;
+      /* Is this line special? */
+      if (c == '#')
+       {
+         /* See if it's a `#line' line. */
+         if ((c = getc (fskel)) == 'l')
+           if ((c = getc (fskel)) == 'i')
+             if ((c = getc (fskel)) == 'n')
+               if ((c = getc (fskel)) == 'e')
+                 line_type = sync_line;
+               else
+                 obstack_sgrow (&table_obstack, "#lin");
+             else
+               obstack_sgrow (&table_obstack, "#li");
+           else
+             obstack_sgrow (&table_obstack, "#l");
+         else
+           obstack_sgrow (&table_obstack, "#");
+       }
+      else if (c == '%')
+       {
+         /* See if it's a `%% actions' line. */
+         if ((c = getc (fskel)) == '%')
+           if ((c = getc (fskel)) == ' ')
+             if ((c = getc (fskel)) == 'a')
+               if ((c = getc (fskel)) == 'c')
+                 if ((c = getc (fskel)) == 't')
+                   if ((c = getc (fskel)) == 'i')
+                     if ((c = getc (fskel)) == 'o')
+                       if ((c = getc (fskel)) == 'n')
+                         if ((c = getc (fskel)) == 's')
+                           line_type = actions_line;
+                         else
+                           obstack_sgrow (&table_obstack, "%% action");
                        else
                        else
-                         fprintf (ftable, "#lin");
-                     }
+                         obstack_sgrow (&table_obstack, "%% actio");
+                     else
+                       obstack_sgrow (&table_obstack, "%% acti");
                    else
                    else
-                     fprintf (ftable, "#li");
-                 }
+                     obstack_sgrow (&table_obstack, "%% act");
+                 else
+                   obstack_sgrow (&table_obstack, "%% ac");
                else
                else
-                 fprintf (ftable, "#l");
-             }
+                 obstack_sgrow (&table_obstack, "%% a");
+             else
+               obstack_sgrow (&table_obstack, "%% ");
            else
            else
-             fprintf (ftable, "#");
-         }
+             obstack_sgrow (&table_obstack, "%%");
+         else
+           obstack_sgrow (&table_obstack, "%");
+       }
+
+      switch (line_type)
+       {
+       case sync_line:
+         if (!no_lines_flag)
+           obstack_fgrow2 (&table_obstack, "#line %d %s\n",
+                           line, quotearg_style (c_quoting_style, skeleton));
 
 
-      /* now write out the line... */
-      for (; c != '\n' && c != EOF; c = getc (fpars))
-       if (write_line)
+         /* Skip the end of line. */
+         for (; c != '\n' && c != EOF; c = getc (fskel))
+           /* nothing */;
+         break;
+
+       case actions_line:
          {
          {
-           if (c == '$')
-             {
-               number_of_dollar_signs++;
-               assert (number_of_dollar_signs == 1);
-               /* `$' in the parser file indicates where to put the actions.
-                  Copy them in at this point.  */
-               rewind (faction);
-               for (c = getc (faction); c != EOF; c = getc (faction))
-                 putc (c, ftable);
-               /* Skip the end of the line containing `$'. */
-               write_line = 0;
-             }
-           else
-             putc (c, ftable);
+           size_t size = obstack_object_size (&action_obstack);
+
+           actions_dumped++;
+           assert (actions_dumped == 1);
+           obstack_grow (&table_obstack,
+                         obstack_finish (&action_obstack),
+                         size);
          }
          }
+
+         /* Skip the end of line. */
+         for (; c != '\n' && c != EOF; c = getc (fskel))
+           /* nothing */;
+         break;
+
+       case regular_line:
+         for (; c != '\n' && c != EOF; c = getc (fskel))
+           obstack_1grow (&table_obstack, c);
+       }
+
       if (c == EOF)
        break;
       if (c == EOF)
        break;
-      putc (c, ftable);
+      obstack_1grow (&table_obstack, c);
+      line++;
     }
     }
-  assert (number_of_dollar_signs == 1);
+  assert (actions_dumped == 1);
+  xfclose (fskel);
 }
 
 static void
 }
 
 static void
@@ -1255,14 +1286,11 @@ output_program (void)
   int c;
 
   if (!no_lines_flag)
   int c;
 
   if (!no_lines_flag)
-    fprintf (ftable, "#line %d \"%s\"\n", lineno, infile);
+    obstack_fgrow2 (&table_obstack, "#line %d %s\n",
+                   lineno, quotearg_style (c_quoting_style, infile));
 
 
-  c = getc (finput);
-  while (c != EOF)
-    {
-      putc (c, ftable);
-      c = getc (finput);
-    }
+  while ((c = getc (finput)) != EOF)
+    obstack_1grow (&table_obstack, c);
 }
 
 
 }
 
 
@@ -1288,39 +1316,38 @@ free_itemsets (void)
 void
 output (void)
 {
 void
 output (void)
 {
-  int c;
-
   /* output_token_defines(ftable);      / * JF put out token defines FIRST */
   /* output_token_defines(ftable);      / * JF put out token defines FIRST */
-  if (!semantic_parser)                /* JF Put out other stuff */
+
+  /* If using a simple parser the definition of YYSTYPE are put into
+     TABLE_OBSTACK.  */
+  if (!semantic_parser)
     {
     {
-      rewind (fattrs);
-      while ((c = getc (fattrs)) != EOF)
-       putc (c, ftable);
+      size_t size = obstack_object_size (&attrs_obstack);
+      obstack_grow (&table_obstack, obstack_finish (&attrs_obstack), size);
     }
     }
-  reader_output_yylsp (ftable);
+  reader_output_yylsp (&table_obstack);
   if (debug_flag)
   if (debug_flag)
-    fputs ("\
+    obstack_sgrow (&table_obstack, "\
 #ifndef YYDEBUG\n\
 # define YYDEBUG 1\n\
 #endif\n\
 #ifndef YYDEBUG\n\
 # define YYDEBUG 1\n\
 #endif\n\
-\n",
-          ftable);
+\n");
 
   if (semantic_parser)
 
   if (semantic_parser)
-    fprintf (ftable, "#include \"%s\"\n", attrsfile);
+    obstack_fgrow1 (&table_obstack, "#include %s\n",
+                   quotearg_style (c_quoting_style, attrsfile));
 
   if (!no_parser_flag)
 
   if (!no_parser_flag)
-    fprintf (ftable, "#include <stdio.h>\n\n");
+    obstack_sgrow (&table_obstack, "#include <stdio.h>\n\n");
 
   /* Make "const" do nothing if not in ANSI C.  */
 
   /* Make "const" do nothing if not in ANSI C.  */
-  fputs ("\
+  obstack_sgrow (&table_obstack, "\
 #ifndef __cplusplus\n\
 # ifndef __STDC__\n\
 #  define const\n\
 # endif\n\
 #endif\n\
 #ifndef __cplusplus\n\
 # ifndef __STDC__\n\
 #  define const\n\
 # endif\n\
 #endif\n\
-\n",
-        ftable);
+\n");
 
   free_itemsets ();
   output_defines ();
 
   free_itemsets ();
   output_defines ();