]> git.saurik.com Git - bison.git/blobdiff - src/output.c
* src/reader.c (read_additionnal_code): Rename %%user_code to
[bison.git] / src / output.c
index f86d2243a37db7b3215d89afe01a91a8aa2a8622..944ebb5483c0a4da2ffe60855544110edc6cff8f 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"
 #include "lalr.h"
 #include "reader.h"
 #include "conflicts.h"
 #include "lalr.h"
 #include "reader.h"
 #include "conflicts.h"
+#include "macrotab.h"
 
 extern void berror PARAMS((const char *));
 
 
 extern void berror PARAMS((const char *));
 
-
-
 static int nvectors;
 static int nentries;
 static short **froms;
 static int nvectors;
 static int nentries;
 static short **froms;
@@ -122,226 +123,86 @@ static short *check;
 static int lowzero;
 static int high;
 
 static int lowzero;
 static int high;
 
+struct obstack macro_obstack;
+struct obstack output_obstack;
 
 
+/* FIXME. */
 
 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_table_data (struct obstack* oout, 
+                  short* table_data, 
+                  short first, 
+                  short begin, 
+                  short end)
 {
 {
-  int i, j;
-
-  fprintf (out, "static const short %s[] = {%6d", table_name, first_value);
-
-  j = 10;
-  for (i = begin; i < end; i++)
+  int i;
+  int j = 1;
+  
+  obstack_fgrow1 (oout, "%6d", first);
+  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
-       {
-         j++;
-       }
-
-      fprintf (out, "%6d", short_table[i]);
-    }
-
-  fprintf (out, "\n};\n");
-}
-
-
-/*--------------------------------------------------------------.
-| output_headers -- Output constant strings to the beginning of |
-| certain files.                                                |
-`--------------------------------------------------------------*/
-
-#define        GUARDSTR        \
-"\n\
-#include \"%s\"\n\
-extern int yyerror;\n\
-extern int yycost;\n\
-extern char * yymsg;\n\
-extern YYSTYPE yyval;\n\
-\n\
-yyguard(n, yyvsp, yylsp)\n\
-register int n;\n\
-register YYSTYPE *yyvsp;\n\
-register YYLTYPE *yylsp;\n\
-{\n\
-  yyerror = 0;\n\
-  yycost = 0;\n\
-  yymsg = 0;\n\
-  switch (n)\n\
-    {"
-
-#define        ACTSTR          \
-"\n\
-#include \"%s\"\n\
-extern YYSTYPE yyval;\n\
-extern int yychar;\n\
-\n\
-yyaction(n, yyvsp, yylsp)\n\
-register int n;\n\
-register YYSTYPE *yyvsp;\n\
-register YYLTYPE *yylsp;\n\
-{\n\
-  switch (n)\n\
-    {"
-
-#define        ACTSTR_SIMPLE   "\n  switch (yyn) {\n"
-
-void
-output_headers (void)
-{
-  if (semantic_parser)
-    fprintf (fguard, GUARDSTR, attrsfile);
-
-  if (noparserflag)
-    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");
-*/
-
-  /* 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);
+       ++j;
+      obstack_fgrow1 (oout, "%6d", table_data[i]);
     }
     }
+  obstack_1grow (oout, 0);
 }
 
 
 }
 
 
-/*-------------------------------------------------------.
-| Output constant strings to the ends of certain files.  |
-`-------------------------------------------------------*/
-
-void
-output_trailers (void)
-{
-  if (semantic_parser)
-    fprintf (fguard, "\n    }\n}\n");
-
-  fprintf (faction, "\n");
-
-  if (noparserflag)
-    return;
-
-  if (semantic_parser)
-    fprintf (faction, "    }\n");
-  fprintf (faction, "}\n");
-}
-
-
-
 static void
 output_token_translations (void)
 {
 static void
 output_token_translations (void)
 {
-  int i, j;
-/*   short *sp; JF unused */
-
-  if (translations)
-    {
-      fprintf (ftable,
-              "\n#define YYTRANSLATE(x) ((unsigned)(x) <= %d ? yytranslate[x] : %d)\n",
-              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");
-    }
-  else
-    {
-      fprintf (ftable, "\n#define YYTRANSLATE(x) (x)\n");
-    }
+  output_table_data (&output_obstack, token_translations, 
+                    0, 1, max_user_token_number + 1);
+  macro_insert ("translate", obstack_finish (&output_obstack));
 }
 
 
 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 noparser option, all tables are generated */
-  if (!semantic_parser && !noparserflag)
-    fprintf (ftable, "\n#if YYDEBUG != 0\n");
-
-  output_short_table (ftable, "yyprhs", rrhs,
-                     0, 1, nrules + 1);
-
-  fprintf (ftable, "\nstatic const short yyrhs[] = {%6d", ritem[0]);
-
-  j = 10;
-  for (sp = ritem + 1; *sp; sp++)
-    {
-      putc (',', ftable);
-
-      if (j >= 10)
-       {
-         putc ('\n', ftable);
-         j = 1;
-       }
-      else
-       {
-         j++;
-       }
-
-      if (*sp > 0)
-       fprintf (ftable, "%6d", *sp);
-      else
-       fprintf (ftable, "     0");
-    }
-
-  fprintf (ftable, "\n};\n");
-
-  if (!semantic_parser && !noparserflag)
-    fprintf (ftable, "\n#endif\n");
+  output_table_data (&output_obstack, rrhs, 
+                    0, 1, nrules + 1);
+  macro_insert ("prhs", obstack_finish (&output_obstack));
+  
+  {
+    size_t yyrhs_size = 1;
+    short *yyrhs, *sp;
+    int i;
+
+    for (sp = ritem + 1; *sp; sp++)
+      ++yyrhs_size;
+    yyrhs = XMALLOC (short, yyrhs_size);
+
+    for (sp = ritem + 1, i = 1; *sp; ++sp, ++i)
+      yyrhs[i] = *sp > 0 ? *sp : 0;
+
+    output_table_data (&output_obstack, yyrhs, 
+                      ritem[0], 1, yyrhs_size);
+    macro_insert ("rhs", obstack_finish (&output_obstack));
+
+    XFREE (yyrhs);
+  }
+
+#if 0
+  if (!semantic_parser && !no_parser_flag)
+    obstack_sgrow (&table_obstack, "\n#endif\n");
+#endif
 }
 
 
 static void
 output_stos (void)
 {
 }
 
 
 static void
 output_stos (void)
 {
-  output_short_table (ftable, "yystos", accessing_symbol,
-                     0, 1, nstates);
+  output_table_data (&output_obstack, accessing_symbol, 
+                    0, 1, nstates);
+  macro_insert ("stos", obstack_finish (&output_obstack));
 }
 
 
 }
 
 
@@ -350,152 +211,88 @@ 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);
-
-  output_short_table (ftable, "yyrline", rline,
-                     0, 1, nrules + 1);
+  output_table_data (&output_obstack, rline,
+                    0, 1, nrules + 1);
+  macro_insert ("rline", obstack_finish (&output_obstack));
 
 
-  fputs ("#endif\n\n", ftable);
-
-  if (toknumflag || noparserflag)
-    {
-      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);
-    }
-
-  if (!toknumflag && !noparserflag)
-    fprintf (ftable, "\n#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)\n\n");
-
-  /* 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++)
+  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 (&output_obstack, "\n  ");
+         j = 2;
        }
 
        }
 
-      putc ('\"', ftable);
-      j++;
-
+      obstack_1grow (&output_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 (&output_obstack, "\\%c", *p);
          else if (*p == '\n')
          else if (*p == '\n')
-           {
-             fprintf (ftable, "\\n");
-             j += 2;
-           }
+           obstack_sgrow (&output_obstack, "\\n");
          else if (*p == '\t')
          else if (*p == '\t')
-           {
-             fprintf (ftable, "\\t");
-             j += 2;
-           }
+           obstack_sgrow (&output_obstack, "\\t");
          else if (*p == '\b')
          else if (*p == '\b')
-           {
-             fprintf (ftable, "\\b");
-             j += 2;
-           }
+           obstack_sgrow (&output_obstack, "\\b");
          else if (*p < 040 || *p >= 0177)
          else if (*p < 040 || *p >= 0177)
-           {
-             fprintf (ftable, "\\%03o", *p);
-             j += 4;
-           }
+           obstack_fgrow1 (&output_obstack, "\\%03o", *p);
          else
          else
-           {
-             putc (*p, ftable);
-             j++;
-           }
+           obstack_1grow (&output_obstack, *p);
        }
 
        }
 
-      putc ('\"', ftable);
-      j++;
+      obstack_sgrow (&output_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 (&output_obstack, "NULL");
 
 
-  if (!toknumflag && !noparserflag)
-    fprintf (ftable, "#endif\n\n");
+  /* Finish table and store. */
+  obstack_1grow (&output_obstack, 0);
+  macro_insert ("tname", obstack_finish (&output_obstack));
 
   /* Output YYTOKNUM. */
 
   /* Output YYTOKNUM. */
-  if (toknumflag)
-    {
-      output_short_table (ftable, "yytoknum", user_toknums,
-                         0, 1, ntokens + 1);
-    }
+  output_table_data (&output_obstack, user_toknums,
+                    0, 1, ntokens + 1);
+  macro_insert ("toknum", obstack_finish (&output_obstack));
 
   /* Output YYR1. */
 
   /* Output YYR1. */
-  fputs ("\
-/* YYR1[YYN]: Symbol number of symbol that rule YYN derives. */\n", ftable);
-
-  output_short_table (ftable, "yyr1", rlhs,
-                     0, 1, nrules + 1);
+  output_table_data (&output_obstack, rlhs, 
+                    0, 1, nrules + 1);
+  macro_insert ("r1", obstack_finish (&output_obstack));
   XFREE (rlhs + 1);
 
   XFREE (rlhs + 1);
 
-  putc ('\n', ftable);
-
   /* 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++;
-       }
+    short_tab[i] = rrhs[i + 1] - rrhs[i] - 1;
+  short_tab[nrules] = nitems - rrhs[nrules] - 1;
+  output_table_data (&output_obstack, short_tab, 
+                    0, 1, nrules + 1);
+  macro_insert ("r2", obstack_finish (&output_obstack));
+  XFREE (short_tab);
 
 
-      fprintf (ftable, "%6d", rrhs[i + 1] - rrhs[i] - 1);
-    }
-
-  putc (',', ftable);
-  if (j >= 10)
-    putc ('\n', ftable);
-
-  fprintf (ftable, "%6d\n};\n", nitems - rrhs[nrules] - 1);
   XFREE (rrhs + 1);
 }
 
   XFREE (rrhs + 1);
 }
 
-
-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);
-}
-
-
 /*------------------------------------------------------------------.
 | Decide what to do for each type of token if seen as the lookahead |
 | token in specified state.  The value returned is used as the      |
 /*------------------------------------------------------------------.
 | Decide what to do for each type of token if seen as the lookahead |
 | token in specified state.  The value returned is used as the      |
@@ -736,10 +533,12 @@ token_actions (void)
       yydefact[i] = action_row (i);
       save_row (i);
     }
       yydefact[i] = action_row (i);
       save_row (i);
     }
-  XFREE (actrow);
 
 
-  output_short_table (ftable, "yydefact", yydefact,
-                     yydefact[0], 1, nstates);
+  output_table_data (&output_obstack, yydefact, 
+                    yydefact[0], 1, nstates);
+  macro_insert ("defact", obstack_finish (&output_obstack));
+  
+  XFREE (actrow);
   XFREE (yydefact);
 }
 
   XFREE (yydefact);
 }
 
@@ -779,19 +578,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 +602,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 +664,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_table_data (&output_obstack, yydefgoto, 
+                    yydefgoto[0], 1, nsyms - ntokens);
+  macro_insert ("defgoto", obstack_finish (&output_obstack));
+
   XFREE (state_count);
   XFREE (state_count);
+  XFREE (yydefgoto);
 }
 
 
 }
 
 
@@ -1095,13 +879,15 @@ pack_table (void)
 static void
 output_base (void)
 {
 static void
 output_base (void)
 {
-  output_short_table (ftable, "yypact", base,
-                     base[0], 1, nstates);
-
-  putc ('\n', ftable);
+  /* Output pact. */
+  output_table_data (&output_obstack, base, 
+                    base[0], 1, nstates);
+  macro_insert ("pact", obstack_finish (&output_obstack));
 
 
-  output_short_table (ftable, "yypgoto", base,
-                     base[nstates], nstates + 1, nvectors);
+  /* Output pgoto. */
+  output_table_data (&output_obstack, base, 
+                    base[nstates], nstates + 1, nvectors);
+  macro_insert ("pgoto", obstack_finish (&output_obstack));
 
   XFREE (base);
 }
 
   XFREE (base);
 }
@@ -1110,9 +896,9 @@ 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,
-                     table[0], 1, high + 1);
+  output_table_data (&output_obstack, table, 
+                    table[0], 1, high + 1);
+  macro_insert ("table", obstack_finish (&output_obstack));
   XFREE (table);
 }
 
   XFREE (table);
 }
 
@@ -1120,8 +906,9 @@ output_table (void)
 static void
 output_check (void)
 {
 static void
 output_check (void)
 {
-  output_short_table (ftable, "yycheck", check,
-                     check[0], 1, high + 1);
+  output_table_data (&output_obstack, check, 
+                    check[0], 1, high + 1);
+  macro_insert ("check", obstack_finish (&output_obstack));
   XFREE (check);
 }
 
   XFREE (check);
 }
 
@@ -1153,111 +940,82 @@ output_actions (void)
 
   sort_actions ();
   pack_table ();
 
   sort_actions ();
   pack_table ();
-  putc ('\n', ftable);
+
   output_base ();
   output_table ();
   output_base ();
   output_table ();
-  putc ('\n', ftable);
+
   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;
-#ifdef DONTDEF
-  FILE *fpars;
-#else
-#define fpars fparser
-#endif
-
-  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
+  FILE *fskel;
+  size_t line;
+  int actions_dumped = 0;
 
   /* Loop over lines in the standard parser file.  */
 
   /* Loop over lines in the standard parser file.  */
-
-  while (1)
+  if (!skeleton)
     {
     {
-      int write_line = 1;
-
-      c = getc (fpars);
-
-      /* See if the line starts with `#line.
-         If so, set write_line to 0.  */
-      if (nolinesflag)
-       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;
-                       else
-                         fprintf (ftable, "#lin");
-                     }
-                   else
-                     fprintf (ftable, "#li");
-                 }
-               else
-                 fprintf (ftable, "#l");
-             }
-           else
-             fprintf (ftable, "#");
-         }
-
-      /* now write out the line... */
-      for (; c != '\n' && c != EOF; c = getc (fpars))
-       if (write_line)
-         {
-           if (c == '$')
-             {
-               /* `$' 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);
-             }
-           else
-             putc (c, ftable);
-         }
-      if (c == EOF)
-       break;
-      putc (c, ftable);
+      if (semantic_parser)
+       skeleton = skeleton_find ("BISON_HAIRY", BISON_HAIRY);
+      else
+       skeleton = skeleton_find ("BISON_SIMPLE", BISON_SIMPLE);
     }
     }
-}
+  fskel = xfopen (skeleton, "r");
 
 
-static void
-output_program (void)
-{
-  int c;
-
-  if (!nolinesflag)
-    fprintf (ftable, "#line %d \"%s\"\n", lineno, infile);
-
-  c = getc (finput);
+  /* New output code. */
+  line = 1;
+  c = getc (fskel);
   while (c != EOF)
     {
   while (c != EOF)
     {
-      putc (c, ftable);
-      c = getc (finput);
+      if (c != '%')
+       {
+         if (c == '\n')
+           ++line;
+         obstack_1grow (&table_obstack, c);
+         c = getc (fskel);
+       }
+      else if ((c = getc (fskel)) == '%')
+       {
+         /* Read the macro. */
+         const char* macro_key = 0;
+         const char* macro_value = 0;
+         while (isalnum (c = getc (fskel)) || c == '_')
+           obstack_1grow (&macro_obstack, c);
+         obstack_1grow (&macro_obstack, 0);
+
+         /* Output the right value, or see if it's something special. */
+         macro_key = obstack_finish (&macro_obstack);
+         macro_value = macro_find (macro_key);
+         if (macro_value)
+           obstack_sgrow (&table_obstack, macro_value);
+         else if (!strcmp (macro_key, "line"))
+           obstack_fgrow1 (&table_obstack, "%d", line + 1);
+         else if (!strcmp (macro_key, "action"))
+           {
+             size_t size = obstack_object_size (&action_obstack);
+             obstack_grow (&table_obstack, 
+                           obstack_finish (&action_obstack), size);
+           }
+         else
+           {
+             obstack_sgrow (&table_obstack, "%%");
+             obstack_sgrow (&table_obstack, macro_key);
+           }
+       }
+      else
+       obstack_1grow (&table_obstack, '%');
     }
     }
-}
 
 
+  /* End. */
+  xfclose (fskel);
+}
 
 static void
 free_itemsets (void)
 
 static void
 free_itemsets (void)
@@ -1273,60 +1031,92 @@ free_itemsets (void)
     }
 }
 
     }
 }
 
+/* FIXME. */
 
 
-/*----------------------------------------------------------.
-| Output the parsing tables and the parser code to ftable.  |
-`----------------------------------------------------------*/
+#define MACRO_INSERT_INT(Key, Value)                   \
+{                                                      \
+  obstack_fgrow1 (&macro_obstack, "%d", Value);                \
+  obstack_1grow (&macro_obstack, 0);                   \
+  macro_insert (Key, obstack_finish (&macro_obstack)); \
+}
 
 
-void
-output (void)
+#define MACRO_INSERT_STRING(Key, Value)                        \
+{                                                      \
+  obstack_sgrow (&macro_obstack, Value);               \
+  obstack_1grow (&macro_obstack, 0);                   \
+  macro_insert (Key, obstack_finish (&macro_obstack)); \
+}
+
+#define MACRO_INSERT_PREFIX(Key, Value)                                        \
+{                                                                      \
+  obstack_fgrow2 (&macro_obstack, "%s%s", spec_name_prefix, Value);    \
+  obstack_1grow (&macro_obstack, 0);                                   \
+  macro_insert (Key, obstack_finish (&macro_obstack));                 \
+}
+
+static void
+prepare (void)
 {
 {
-  int c;
+  MACRO_INSERT_INT ("last", high);
+  MACRO_INSERT_INT ("flag", MINSHORT);
+  MACRO_INSERT_INT ("pure", pure_parser);
+  MACRO_INSERT_INT ("nsym", nsyms);
+  MACRO_INSERT_INT ("debug", debug_flag);
+  MACRO_INSERT_INT ("final", final_state);
+  MACRO_INSERT_INT ("maxtok", max_user_token_number);
+  MACRO_INSERT_INT ("ntbase", ntokens);
+  MACRO_INSERT_INT ("verbose", 0);
+
+  MACRO_INSERT_STRING ("filename", infile);
+
+  MACRO_INSERT_INT ("nnts", nvars);
+  MACRO_INSERT_INT ("nrules", nrules);
+  MACRO_INSERT_INT ("nstates", nstates);
+  MACRO_INSERT_INT ("ntokens", ntokens);
 
 
-  /* output_token_defines(ftable);      / * JF put out token defines FIRST */
-  if (!semantic_parser)                /* JF Put out other stuff */
+  if (spec_name_prefix)
     {
     {
-      rewind (fattrs);
-      while ((c = getc (fattrs)) != EOF)
-       putc (c, ftable);
+      MACRO_INSERT_PREFIX ("yylex", "lex");
+      MACRO_INSERT_PREFIX ("yychar", "char");
+      MACRO_INSERT_PREFIX ("yylval", "lval");
+      MACRO_INSERT_PREFIX ("yydebug", "debug");
+      MACRO_INSERT_PREFIX ("yyerror", "error");
+      MACRO_INSERT_PREFIX ("yynerrs", "nerrs");
+      MACRO_INSERT_PREFIX ("yyparse", "parse");
     }
     }
-  reader_output_yylsp (ftable);
-  if (debugflag)
-    fputs ("\
-#ifndef YYDEBUG\n\
-#define YYDEBUG 1\n\
-#endif\n\
-\n",
-          ftable);
-
-  if (semantic_parser)
-    fprintf (ftable, "#include \"%s\"\n", attrsfile);
+}
 
 
-  if (!noparserflag)
-    fprintf (ftable, "#include <stdio.h>\n\n");
+/*----------------------------------------------------------.
+| Output the parsing tables and the parser code to ftable.  |
+`----------------------------------------------------------*/
 
 
-  /* Make "const" do nothing if not in ANSI C.  */
-  fputs ("\
-#ifndef __cplusplus\n\
-# ifndef __STDC__\n\
-#  define const\n\
-# endif\n\
-#endif\n\
-\n",
-        ftable);
+void
+output (void)
+{
+  obstack_init (&output_obstack);
 
 
+#if 0
+  reader_output_yylsp (&table_obstack); */
+#endif
   free_itemsets ();
   free_itemsets ();
-  output_defines ();
+
   output_token_translations ();
   output_token_translations ();
-/*   if (semantic_parser) */
-  /* This is now unconditional because debugging printouts can use it.  */
   output_gram ();
   output_gram ();
+
   XFREE (ritem);
   if (semantic_parser)
     output_stos ();
   output_rule_data ();
   output_actions ();
   XFREE (ritem);
   if (semantic_parser)
     output_stos ();
   output_rule_data ();
   output_actions ();
-  if (!noparserflag)
-    output_parser ();
-  output_program ();
+  
+#if 0
+  if (!no_parser_flag) */
+#endif
+  prepare ();
+  /* Copy definitions in directive.  */
+  macro_insert ("prologue", obstack_finish (&attrs_obstack));
+  output_parser ();
+
+  obstack_free (&macro_obstack, 0);
+  obstack_free (&output_obstack, 0);
 }
 }