]> git.saurik.com Git - bison.git/blobdiff - src/output.c
* configure.in: Check the protos of strchr ans strspn.
[bison.git] / src / output.c
index b86f461134c38884a62a8509f4c39875c4ccbd33..34ff7d36551e6bf32c7551def2ff78eca1f209d0 100644 (file)
@@ -1,5 +1,5 @@
 /* Output the generated parsing program for bison,
 /* Output the generated parsing program for bison,
-   Copyright 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.
 
 */
 
 #include "system.h"
 */
 
 #include "system.h"
-#include "obstack.h"
 #include "quotearg.h"
 #include "getargs.h"
 #include "quotearg.h"
 #include "getargs.h"
-#include "xalloc.h"
 #include "files.h"
 #include "gram.h"
 #include "LR0.h"
 #include "files.h"
 #include "gram.h"
 #include "LR0.h"
 #include "lalr.h"
 #include "reader.h"
 #include "conflicts.h"
 #include "lalr.h"
 #include "reader.h"
 #include "conflicts.h"
-
-extern void berror PARAMS((const char *));
-
+#include "muscle_tab.h"
 
 
 static int nvectors;
 static int nentries;
 
 
 static int nvectors;
 static int nentries;
-static short **froms;
-static short **tos;
-static short *tally;
-static short *width;
-static short *actrow;
-static short *state_count;
-static short *order;
-static short *base;
-static short *pos;
-static short *table;
-static short *check;
+static short **froms = NULL;
+static short **tos = NULL;
+static short *tally = NULL;
+static short *width = NULL;
+static short *actrow = NULL;
+static short *state_count = NULL;
+static short *order = NULL;
+static short *base = NULL;
+static short *pos = NULL;
+static short *table = NULL;
+static short *check = NULL;
 static int lowzero;
 static int high;
 
 static int lowzero;
 static int high;
 
+struct obstack muscle_obstack;
+static struct obstack format_obstack;
 
 
+int error_verbose = 0;
 
 
-static inline void
-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)
+/* Returns the number of lines of S.  */
+static size_t
+get_lines_number (const char *s)
 {
 {
-  int i, j;
+  size_t lines = 0;
+
+  size_t i;
+  for (i = 0; s[i]; ++i)
+    if (s[i] == '\n')
+      ++lines;
 
 
-  if (comment)
-    obstack_fgrow1 (oout, "/* %s. */\n", comment);
+  return lines;
+}
 
 
-  obstack_fgrow3 (oout, "static const %s %s[] =\n{\n  %6d",
-                 type, table_name, first_value);
 
 
-  j = 1;
-  for (i = begin; i < end; i++)
+/* FIXME. */
+
+static inline void
+output_table_data (struct obstack *oout,
+                  short *table_data,
+                  short first,
+                  int begin,
+                  int end)
+{
+  int i;
+  int j = 1;
+
+  obstack_fgrow1 (oout, "%6d", first);
+  for (i = begin; i < end; ++i)
     {
       obstack_1grow (oout, ',');
     {
       obstack_1grow (oout, ',');
-
       if (j >= 10)
        {
          obstack_sgrow (oout, "\n  ");
          j = 1;
        }
       else
       if (j >= 10)
        {
          obstack_sgrow (oout, "\n  ");
          j = 1;
        }
       else
-       {
-         j++;
-       }
-
-      obstack_fgrow1 (oout, "%6d", short_table[i]);
-    }
-
-  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);
-}
-
-
-/*--------------------------------------------------------------.
-| output_headers -- Output constant strings to the beginning of |
-| certain files.                                                |
-`--------------------------------------------------------------*/
-
-/* Don't put the `%s' insides quotes, since it quotearg puts them. */
-
-#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)
-{
-  char *attrsfile_quoted = 0;
-
-  if (semantic_parser)
-    {
-      /* 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 (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)
-    {
-      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);
+       ++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)
-    obstack_sgrow (&guard_obstack, "\n    }\n}\n");
-
-  obstack_1grow (&action_obstack, '\n');
-
-  if (no_parser_flag)
-    return;
-
-  if (semantic_parser)
-    obstack_sgrow (&action_obstack, "    }\n");
-
-  obstack_sgrow (&action_obstack, "}\n");
-}
-
-
-
 static void
 output_token_translations (void)
 {
 static void
 output_token_translations (void)
 {
-  obstack_sgrow (&table_obstack, "\
-\n\
-/* YYRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */\n");
-
-  if (translations)
-    {
-      obstack_fgrow2 (&table_obstack,
-      "#define YYTRANSLATE(x) ((unsigned)(x) <= %d ? yytranslate[x] : %d)\
-\n\
-\n",
-              max_user_token_number, nsyms);
-
-      output_short_or_char_table (&table_obstack,
-            "YYRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX",
-                   ntokens < 127 ? "char" : "short",
-                   "yytranslate", token_translations,
-                   0, 1, max_user_token_number + 1);
-    }
-  else
-    {
-      obstack_sgrow (&table_obstack,
-                          "\n#define YYTRANSLATE(x) (x)\n");
-    }
+  output_table_data (&format_obstack, token_translations,
+                    0, 1, max_user_token_number + 1);
+  muscle_insert ("translate", obstack_finish (&format_obstack));
+  XFREE (token_translations);
 }
 
 
 static void
 output_gram (void)
 {
 }
 
 
 static void
 output_gram (void)
 {
-  /* 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)
-    obstack_sgrow (&table_obstack, "\n#if YYDEBUG != 0\n");
+  {
+    int i;
+    short *values = XCALLOC (short, nrules + 1);
+    for (i = 0; i < nrules + 1; ++i)
+      values[i] = rule_table[i].rhs;
+    output_table_data (&format_obstack, values,
+                      0, 1, nrules + 1);
+    XFREE (values);
+  }
 
 
-  output_short_table (&table_obstack, NULL, "yyprhs", rrhs,
-                     0, 1, nrules + 1);
+  muscle_insert ("prhs", obstack_finish (&format_obstack));
 
   {
     size_t yyrhs_size = 1;
 
   {
     size_t yyrhs_size = 1;
@@ -341,21 +206,30 @@ output_gram (void)
     for (sp = ritem + 1, i = 1; *sp; ++sp, ++i)
       yyrhs[i] = *sp > 0 ? *sp : 0;
 
     for (sp = ritem + 1, i = 1; *sp; ++sp, ++i)
       yyrhs[i] = *sp > 0 ? *sp : 0;
 
-    output_short_table (&table_obstack, NULL, "yyrhs", yyrhs,
-                       ritem[0], 1, yyrhs_size);
+    output_table_data (&format_obstack, yyrhs,
+                      ritem[0], 1, yyrhs_size);
+    muscle_insert ("rhs", obstack_finish (&format_obstack));
+
     XFREE (yyrhs);
   }
 
     XFREE (yyrhs);
   }
 
-  if (!semantic_parser && !no_parser_flag)
+#if 0
+  if (!semantic_parser)
     obstack_sgrow (&table_obstack, "\n#endif\n");
     obstack_sgrow (&table_obstack, "\n#endif\n");
+#endif
 }
 
 
 static void
 output_stos (void)
 {
 }
 
 
 static void
 output_stos (void)
 {
-  output_short_table (&table_obstack, NULL, "yystos", accessing_symbol,
-                     0, 1, nstates);
+  int i;
+  short *values = (short *) alloca (sizeof (short) * nstates);
+  for (i = 0; i < nstates; ++i)
+    values[i] = state_table[i]->accessing_symbol;
+  output_table_data (&format_obstack, values,
+                    0, 1, nstates);
+  muscle_insert ("stos", obstack_finish (&format_obstack));
 }
 
 
 }
 
 
@@ -366,130 +240,72 @@ output_rule_data (void)
   int j;
   short *short_tab = NULL;
 
   int j;
   short *short_tab = NULL;
 
-  obstack_sgrow (&table_obstack, "\n\
-#if YYDEBUG != 0\n");
-
-  output_short_table (&table_obstack,
-           "YYRLINE[YYN] -- source line where rule number YYN was defined",
-                     "yyrline", rline,
-                     0, 1, nrules + 1);
-
-  obstack_sgrow (&table_obstack, "#endif\n\n");
-
-  if (token_table_flag || no_parser_flag)
-    {
-      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);
-    }
+  {
+    short *values = XCALLOC (short, nrules + 1);
+    for (i = 0; i < nrules + 1; ++i)
+      values[i] = rule_table[i].line;
+    output_table_data (&format_obstack, values,
+                      0, 1, nrules + 1);
+    muscle_insert ("rline", obstack_finish (&format_obstack));
+    XFREE (values);
+  }
 
 
-  /* Output the table of symbol names.  */
-  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++)
 
   j = 0;
   for (i = 0; i < nsyms; i++)
-    /* this used to be i<=nsyms, but that output a final "" symbol
-       almost by accident */
     {
     {
+      /* Be sure not to use twice the same quotearg slot. */
+      const char *cp =
+       quotearg_n_style (1, c_quoting_style,
+                         quotearg_style (escape_quoting_style, tags[i]));
       /* Width of the next token, including the two quotes, the coma
         and the space.  */
       /* Width of the next token, including the two quotes, the coma
         and the space.  */
-      int strsize = 4;
-      char *p;
-
-      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++;
+      int strsize = strlen (cp) + 2;
 
       if (j + strsize > 75)
        {
 
       if (j + strsize > 75)
        {
-         obstack_sgrow (&table_obstack, "\n  ");
+         obstack_sgrow (&format_obstack, "\n  ");
          j = 2;
        }
 
          j = 2;
        }
 
-      obstack_1grow (&table_obstack, '\"');
-      for (p = tags[i]; p && *p; p++)
-       {
-         if (*p == '"' || *p == '\\')
-           obstack_fgrow1 (&table_obstack, "\\%c", *p);
-         else if (*p == '\n')
-           obstack_sgrow (&table_obstack, "\\n");
-         else if (*p == '\t')
-           obstack_sgrow (&table_obstack, "\\t");
-         else if (*p == '\b')
-           obstack_sgrow (&table_obstack, "\\b");
-         else if (*p < 040 || *p >= 0177)
-           obstack_fgrow1 (&table_obstack, "\\%03o", *p);
-         else
-           obstack_1grow (&table_obstack, *p);
-       }
-
-      obstack_sgrow (&table_obstack, "\", ");
+      obstack_sgrow (&format_obstack, cp);
+      obstack_sgrow (&format_obstack, ", ");
       j += strsize;
     }
   /* add a NULL entry to list of tokens */
       j += strsize;
     }
   /* add a NULL entry to list of tokens */
-  obstack_sgrow (&table_obstack, "NULL\n};\n");
+  obstack_sgrow (&format_obstack, "NULL");
 
 
-  if (!token_table_flag && !no_parser_flag)
-    obstack_sgrow (&table_obstack, "#endif\n\n");
+  /* Finish table and store. */
+  obstack_1grow (&format_obstack, 0);
+  muscle_insert ("tname", obstack_finish (&format_obstack));
 
   /* Output YYTOKNUM. */
 
   /* Output YYTOKNUM. */
-  if (token_table_flag)
-    {
-      output_short_table (&table_obstack,
-                 "YYTOKNUM[YYLEX] -- Index in YYTNAME corresponding to YYLEX",
-                         "yytoknum", user_toknums,
-                         0, 1, ntokens + 1);
-    }
+  output_table_data (&format_obstack, user_toknums,
+                    0, 1, ntokens + 1);
+  muscle_insert ("toknum", obstack_finish (&format_obstack));
 
   /* Output YYR1. */
 
   /* Output YYR1. */
-  output_short_table (&table_obstack,
-             "YYR1[YYN] -- Symbol number of symbol that rule YYN derives",
-                     "yyr1", rlhs,
-                     0, 1, nrules + 1);
-  XFREE (rlhs + 1);
-
-  obstack_1grow (&table_obstack, '\n');
+  {
+    short *values = XCALLOC (short, nrules + 1);
+    for (i = 0; i < nrules + 1; ++i)
+      values[i] = rule_table[i].lhs;
+    output_table_data (&format_obstack, values,
+                      0, 1, nrules + 1);
+    muscle_insert ("r1", obstack_finish (&format_obstack));
+    XFREE (values);
+  }
 
   /* Output YYR2. */
   short_tab = XMALLOC (short, nrules + 1);
   for (i = 1; i < nrules; i++)
 
   /* Output YYR2. */
   short_tab = XMALLOC (short, nrules + 1);
   for (i = 1; i < nrules; i++)
-    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');
-
+    short_tab[i] = rule_table[i + 1].rhs - rule_table[i].rhs - 1;
+  short_tab[nrules] =  nitems - rule_table[nrules].rhs - 1;
+  output_table_data (&format_obstack, short_tab,
+                    0, 1, nrules + 1);
+  muscle_insert ("r2", obstack_finish (&format_obstack));
   XFREE (short_tab);
   XFREE (short_tab);
-
-  XFREE (rrhs + 1);
-}
-
-
-static void
-output_defines (void)
-{
-  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);
 }
 
 }
 
-
 /*------------------------------------------------------------------.
 | 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      |
@@ -505,137 +321,84 @@ output_defines (void)
 `------------------------------------------------------------------*/
 
 static int
 `------------------------------------------------------------------*/
 
 static int
-action_row (int state)
+action_row (state_t *state)
 {
   int i;
 {
   int i;
-  int j;
-  int k;
-  int m = 0;
-  int n = 0;
-  int count;
-  int default_rule;
-  int nreds;
-  int max;
-  int rule;
-  int shift_state;
-  int symbol;
-  unsigned mask;
-  unsigned *wordp;
-  reductions *redp;
-  shifts *shiftp;
-  errs *errp;
-  int nodefault = 0;           /* set nonzero to inhibit having any default reduction */
+  int default_rule = 0;
+  reductions *redp = state->reductions;
+  shifts *shiftp = state->shifts;
+  errs *errp = state->errs;
+  /* set nonzero to inhibit having any default reduction */
+  int nodefault = 0;
 
   for (i = 0; i < ntokens; i++)
     actrow[i] = 0;
 
 
   for (i = 0; i < ntokens; i++)
     actrow[i] = 0;
 
-  default_rule = 0;
-  nreds = 0;
-  redp = reduction_table[state];
-
-  if (redp)
+  if (redp->nreds >= 1)
     {
     {
-      nreds = redp->nreds;
-
-      if (nreds >= 1)
-       {
-         /* loop over all the rules available here which require
-            lookahead */
-         m = lookaheads[state];
-         n = lookaheads[state + 1];
-
-         for (i = n - 1; i >= m; i--)
-           {
-             rule = -LAruleno[i];
-             wordp = LA + i * tokensetsize;
-             mask = 1;
-
-             /* and find each token which the rule finds acceptable
-                to come next */
-             for (j = 0; j < ntokens; j++)
-               {
-                 /* and record this rule as the rule to use if that
-                    token follows.  */
-                 if (mask & *wordp)
-                   actrow[j] = rule;
-
-                 mask <<= 1;
-                 if (mask == 0)
-                   {
-                     mask = 1;
-                     wordp++;
-                   }
-               }
-           }
-       }
+      int j;
+      /* loop over all the rules available here which require
+        lookahead */
+      for (i = state->nlookaheads - 1; i >= 0; --i)
+       /* and find each token which the rule finds acceptable
+          to come next */
+       for (j = 0; j < ntokens; j++)
+         /* and record this rule as the rule to use if that
+            token follows.  */
+         if (BITISSET (LA (state->lookaheadsp + i), j))
+           actrow[j] = -LAruleno[state->lookaheadsp + i];
     }
 
     }
 
-  shiftp = shift_table[state];
-
   /* Now see which tokens are allowed for shifts in this state.  For
      them, record the shift as the thing to do.  So shift is preferred
      to reduce.  */
   /* Now see which tokens are allowed for shifts in this state.  For
      them, record the shift as the thing to do.  So shift is preferred
      to reduce.  */
-
-  if (shiftp)
+  for (i = 0; i < shiftp->nshifts; i++)
     {
     {
-      k = shiftp->nshifts;
+      int symbol;
+      int shift_state = shiftp->shifts[i];
+      if (!shift_state)
+       continue;
 
 
-      for (i = 0; i < k; i++)
-       {
-         shift_state = shiftp->shifts[i];
-         if (!shift_state)
-           continue;
-
-         symbol = accessing_symbol[shift_state];
+      symbol = state_table[shift_state]->accessing_symbol;
 
 
-         if (ISVAR (symbol))
-           break;
+      if (ISVAR (symbol))
+       break;
 
 
-         actrow[symbol] = shift_state;
+      actrow[symbol] = shift_state;
 
 
-         /* Do not use any default reduction if there is a shift for
-            error */
-         if (symbol == error_token_number)
-           nodefault = 1;
-       }
+      /* Do not use any default reduction if there is a shift for
+        error */
+      if (symbol == error_token_number)
+       nodefault = 1;
     }
 
     }
 
-  errp = err_table[state];
-
   /* See which tokens are an explicit error in this state (due to
      %nonassoc).  For them, record MINSHORT as the action.  */
   /* See which tokens are an explicit error in this state (due to
      %nonassoc).  For them, record MINSHORT as the action.  */
-
-  if (errp)
+  for (i = 0; i < errp->nerrs; i++)
     {
     {
-      k = errp->nerrs;
-
-      for (i = 0; i < k; i++)
-       {
-         symbol = errp->errs[i];
-         actrow[symbol] = MINSHORT;
-       }
+      int symbol = errp->errs[i];
+      actrow[symbol] = MINSHORT;
     }
 
   /* Now find the most common reduction and make it the default action
      for this state.  */
 
     }
 
   /* Now find the most common reduction and make it the default action
      for this state.  */
 
-  if (nreds >= 1 && !nodefault)
+  if (redp->nreds >= 1 && !nodefault)
     {
     {
-      if (consistent[state])
+      if (state->consistent)
        default_rule = redp->rules[0];
       else
        {
        default_rule = redp->rules[0];
       else
        {
-         max = 0;
-         for (i = m; i < n; i++)
+         int max = 0;
+         for (i = 0; i < state->nlookaheads; i++)
            {
            {
-             count = 0;
-             rule = -LAruleno[i];
+             int count = 0;
+             int rule = -LAruleno[state->lookaheadsp + i];
+             int j;
 
              for (j = 0; j < ntokens; j++)
 
              for (j = 0; j < ntokens; j++)
-               {
-                 if (actrow[j] == rule)
-                   count++;
-               }
+               if (actrow[j] == rule)
+                 count++;
 
              if (count > max)
                {
 
              if (count > max)
                {
@@ -649,11 +412,10 @@ action_row (int state)
 
          if (max > 0)
            {
 
          if (max > 0)
            {
+             int j;
              for (j = 0; j < ntokens; j++)
              for (j = 0; j < ntokens; j++)
-               {
-                 if (actrow[j] == default_rule)
-                   actrow[j] = 0;
-               }
+               if (actrow[j] == default_rule)
+                 actrow[j] = 0;
 
              default_rule = -default_rule;
            }
 
              default_rule = -default_rule;
            }
@@ -664,11 +426,9 @@ action_row (int state)
      So replace any action which says "error" with "use default".  */
 
   if (default_rule == 0)
      So replace any action which says "error" with "use default".  */
 
   if (default_rule == 0)
-    for (j = 0; j < ntokens; j++)
-      {
-       if (actrow[j] == MINSHORT)
-         actrow[j] = 0;
-      }
+    for (i = 0; i < ntokens; i++)
+      if (actrow[i] == MINSHORT)
+       actrow[i] = 0;
 
   return default_rule;
 }
 
   return default_rule;
 }
@@ -685,10 +445,8 @@ save_row (int state)
 
   count = 0;
   for (i = 0; i < ntokens; i++)
 
   count = 0;
   for (i = 0; i < ntokens; i++)
-    {
-      if (actrow[i] != 0)
-       count++;
-    }
+    if (actrow[i] != 0)
+      count++;
 
   if (count == 0)
     return;
 
   if (count == 0)
     return;
@@ -697,13 +455,11 @@ save_row (int state)
   tos[state] = sp2 = XCALLOC (short, count);
 
   for (i = 0; i < ntokens; i++)
   tos[state] = sp2 = XCALLOC (short, count);
 
   for (i = 0; i < ntokens; i++)
-    {
-      if (actrow[i] != 0)
-       {
-         *sp1++ = i;
-         *sp2++ = actrow[i];
-       }
-    }
+    if (actrow[i] != 0)
+      {
+       *sp1++ = i;
+       *sp2++ = actrow[i];
+      }
 
   tally[state] = count;
   width[state] = sp1[-1] - sp[0] + 1;
 
   tally[state] = count;
   width[state] = sp1[-1] - sp[0] + 1;
@@ -727,53 +483,87 @@ token_actions (void)
   actrow = XCALLOC (short, ntokens);
   for (i = 0; i < nstates; ++i)
     {
   actrow = XCALLOC (short, ntokens);
   for (i = 0; i < nstates; ++i)
     {
-      yydefact[i] = action_row (i);
+      yydefact[i] = action_row (state_table[i]);
       save_row (i);
     }
       save_row (i);
     }
-  XFREE (actrow);
 
 
-  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);
-  obstack_1grow (&table_obstack, '\n');
+  output_table_data (&format_obstack, yydefact,
+                    yydefact[0], 1, nstates);
+  muscle_insert ("defact", obstack_finish (&format_obstack));
+
+  XFREE (actrow);
   XFREE (yydefact);
 }
 
 
   XFREE (yydefact);
 }
 
 
+/*-----------------------------.
+| Output the actions to OOUT.  |
+`-----------------------------*/
+
 static void
 static void
-free_shifts (void)
+actions_output (FILE *out, size_t *line)
 {
 {
-  shifts *sp, *sptmp;  /* JF derefrenced freed ptr */
-
-  XFREE (shift_table);
-
-  for (sp = first_shift; sp; sp = sptmp)
-    {
-      sptmp = sp->next;
-      XFREE (sp);
-    }
+  int rule;
+  for (rule = 1; rule < nrules + 1; ++rule)
+    if (rule_table[rule].action)
+      {
+       fprintf (out, "  case %d:\n", rule);
+
+       if (!no_lines_flag)
+         fprintf (out, muscle_find ("linef"),
+                  rule_table[rule].action_line,
+                  quotearg_style (c_quoting_style,
+                                  muscle_find ("filename")));
+       /* As a Bison extension, add the ending semicolon.  Since some
+          Yacc don't do that, help people using bison as a Yacc
+          finding their missing semicolons.  */
+       fprintf (out, "{ %s%s }\n    break;\n\n",
+                rule_table[rule].action,
+                yacc_flag ? ";" : "");
+
+       /* We always output 4 '\n' per action.  */
+       *line += 4;
+       /* Plus one if !no_lines_flag.  */
+       if (!no_lines_flag)
+         ++*line;
+       /* Get the number of lines written by the user.  */
+       *line += get_lines_number (rule_table[rule].action);
+      }
 }
 
 
 }
 
 
+/*----------------------------.
+| Output the guards to OOUT.  |
+`----------------------------*/
+
 static void
 static void
-free_reductions (void)
+guards_output (FILE *out, size_t *line)
 {
 {
-  reductions *rp, *rptmp;      /* JF fixed freed ptr */
-
-  XFREE (reduction_table);
-
-  for (rp = first_reduction; rp; rp = rptmp)
-    {
-      rptmp = rp->next;
-      XFREE (rp);
-    }
+  int rule;
+  for (rule = 1; rule < nrules + 1; ++rule)
+    if (rule_table[rule].action)
+      {
+       fprintf (out, "  case %d:\n", rule);
+
+       if (!no_lines_flag)
+         fprintf (out, muscle_find ("linef"),
+                  rule_table[rule].guard_line,
+                  quotearg_style (c_quoting_style,
+                                  muscle_find ("filename")));
+       fprintf (out, "{ %s; }\n    break;\n\n",
+                rule_table[rule].guard);
+
+       /* We always output 4 '\n' per action.  */
+       *line += 4;
+       /* Plus one if !no_lines_flag.  */
+       if (!no_lines_flag)
+         ++*line;
+       /* Get the number of lines written by the user.  */
+       *line += get_lines_number (rule_table[rule].guard);
+      }
 }
 
 
 }
 
 
-
 static void
 save_column (int symbol, int default_state)
 {
 static void
 save_column (int symbol, int default_state)
 {
@@ -782,34 +572,28 @@ save_column (int symbol, int default_state)
   short *sp1;
   short *sp2;
   int count;
   short *sp1;
   short *sp2;
   int count;
-  int symno;
+  int symno = symbol - ntokens + nstates;
 
   short begin = goto_map[symbol];
   short end = goto_map[symbol + 1];
 
   count = 0;
   for (i = begin; i < end; i++)
 
   short begin = goto_map[symbol];
   short end = goto_map[symbol + 1];
 
   count = 0;
   for (i = begin; i < end; i++)
-    {
-      if (to_state[i] != default_state)
-       count++;
-    }
+    if (to_state[i] != default_state)
+      count++;
 
   if (count == 0)
     return;
 
 
   if (count == 0)
     return;
 
-  symno = symbol - ntokens + nstates;
-
   froms[symno] = sp1 = sp = XCALLOC (short, count);
   tos[symno] = sp2 = XCALLOC (short, count);
 
   for (i = begin; i < end; i++)
   froms[symno] = sp1 = sp = XCALLOC (short, count);
   tos[symno] = sp2 = XCALLOC (short, count);
 
   for (i = begin; i < end; i++)
-    {
-      if (to_state[i] != default_state)
-       {
-         *sp1++ = from_state[i];
-         *sp2++ = to_state[i];
-       }
-    }
+    if (to_state[i] != default_state)
+      {
+       *sp1++ = from_state[i];
+       *sp2++ = to_state[i];
+      }
 
   tally[symno] = count;
   width[symno] = sp1[-1] - sp[0] + 1;
 
   tally[symno] = count;
   width[symno] = sp1[-1] - sp[0] + 1;
@@ -819,13 +603,10 @@ static int
 default_goto (int symbol)
 {
   int i;
 default_goto (int symbol)
 {
   int i;
-  int m;
-  int n;
-  int default_state;
-  int max;
-
-  m = goto_map[symbol];
-  n = goto_map[symbol + 1];
+  int m = goto_map[symbol];
+  int n = goto_map[symbol + 1];
+  int default_state = -1;
+  int max = 0;
 
   if (m == n)
     return -1;
 
   if (m == n)
     return -1;
@@ -836,17 +617,12 @@ default_goto (int symbol)
   for (i = m; i < n; i++)
     state_count[to_state[i]]++;
 
   for (i = m; i < n; i++)
     state_count[to_state[i]]++;
 
-  max = 0;
-  default_state = -1;
-
   for (i = 0; i < nstates; i++)
   for (i = 0; i < nstates; i++)
-    {
-      if (state_count[i] > max)
-       {
-         max = state_count[i];
-         default_state = i;
-       }
-    }
+    if (state_count[i] > max)
+      {
+       max = state_count[i];
+       default_state = i;
+      }
 
   return default_state;
 }
 
   return default_state;
 }
@@ -865,10 +641,9 @@ static void
 goto_actions (void)
 {
   int i;
 goto_actions (void)
 {
   int i;
-
   short *yydefgoto = XMALLOC (short, nsyms - ntokens);
   short *yydefgoto = XMALLOC (short, nsyms - ntokens);
-  state_count = XCALLOC (short, nstates);
 
 
+  state_count = XCALLOC (short, nstates);
   for (i = ntokens; i < nsyms; ++i)
     {
       int default_state = default_goto (i);
   for (i = ntokens; i < nsyms; ++i)
     {
       int default_state = default_goto (i);
@@ -876,8 +651,9 @@ goto_actions (void)
       yydefgoto[i - ntokens] = default_state;
     }
 
       yydefgoto[i - ntokens] = default_state;
     }
 
-  output_short_table (&table_obstack, NULL, "yydefgoto", yydefgoto,
-                     yydefgoto[0], 1, nsyms - ntokens);
+  output_table_data (&format_obstack, yydefgoto,
+                    yydefgoto[0], 1, nsyms - ntokens);
+  muscle_insert ("defgoto", obstack_finish (&format_obstack));
 
   XFREE (state_count);
   XFREE (yydefgoto);
 
   XFREE (state_count);
   XFREE (yydefgoto);
@@ -891,50 +667,41 @@ static void
 sort_actions (void)
 {
   int i;
 sort_actions (void)
 {
   int i;
-  int j;
-  int k;
-  int t;
-  int w;
 
   order = XCALLOC (short, nvectors);
   nentries = 0;
 
   for (i = 0; i < nvectors; i++)
 
   order = XCALLOC (short, nvectors);
   nentries = 0;
 
   for (i = 0; i < nvectors; i++)
-    {
-      if (tally[i] > 0)
-       {
-         t = tally[i];
-         w = width[i];
-         j = nentries - 1;
+    if (tally[i] > 0)
+      {
+       int k;
+       int t = tally[i];
+       int w = width[i];
+       int j = nentries - 1;
 
 
-         while (j >= 0 && (width[order[j]] < w))
-           j--;
+       while (j >= 0 && (width[order[j]] < w))
+         j--;
 
 
-         while (j >= 0 && (width[order[j]] == w) && (tally[order[j]] < t))
-           j--;
+       while (j >= 0 && (width[order[j]] == w) && (tally[order[j]] < t))
+         j--;
 
 
-         for (k = nentries - 1; k > j; k--)
-           order[k + 1] = order[k];
+       for (k = nentries - 1; k > j; k--)
+         order[k + 1] = order[k];
 
 
-         order[j + 1] = i;
-         nentries++;
-       }
-    }
+       order[j + 1] = i;
+       nentries++;
+      }
 }
 
 
 static int
 matching_state (int vector)
 {
 }
 
 
 static int
 matching_state (int vector)
 {
-  int i;
-  int j;
-  int k;
+  int i = order[vector];
   int t;
   int w;
   int t;
   int w;
-  int match;
   int prev;
 
   int prev;
 
-  i = order[vector];
   if (i >= nstates)
     return -1;
 
   if (i >= nstates)
     return -1;
 
@@ -943,16 +710,16 @@ matching_state (int vector)
 
   for (prev = vector - 1; prev >= 0; prev--)
     {
 
   for (prev = vector - 1; prev >= 0; prev--)
     {
-      j = order[prev];
+      int j = order[prev];
+      int k;
+      int match = 1;
+
       if (width[j] != w || tally[j] != t)
        return -1;
 
       if (width[j] != w || tally[j] != t)
        return -1;
 
-      match = 1;
       for (k = 0; match && k < t; k++)
       for (k = 0; match && k < t; k++)
-       {
-         if (tos[j][k] != tos[i][k] || froms[j][k] != froms[i][k])
-           match = 0;
-       }
+       if (tos[j][k] != tos[i][k] || froms[j][k] != froms[i][k])
+         match = 0;
 
       if (match)
        return j;
 
       if (match)
        return j;
@@ -965,26 +732,19 @@ matching_state (int vector)
 static int
 pack_vector (int vector)
 {
 static int
 pack_vector (int vector)
 {
-  int i;
+  int i = order[vector];
   int j;
   int j;
-  int k;
-  int t;
+  int t = tally[i];
   int loc = 0;
   int loc = 0;
-  int ok;
-  short *from;
-  short *to;
-
-  i = order[vector];
-  t = tally[i];
+  short *from = froms[i];
+  short *to = tos[i];
 
   assert (t);
 
 
   assert (t);
 
-  from = froms[i];
-  to = tos[i];
-
   for (j = lowzero - from[0]; j < MAXTABLE; j++)
     {
   for (j = lowzero - from[0]; j < MAXTABLE; j++)
     {
-      ok = 1;
+      int k;
+      int ok = 1;
 
       for (k = 0; ok && k < t; k++)
        {
 
       for (k = 0; ok && k < t; k++)
        {
@@ -997,10 +757,8 @@ pack_vector (int vector)
        }
 
       for (k = 0; ok && k < vector; k++)
        }
 
       for (k = 0; ok && k < vector; k++)
-       {
-         if (pos[k] == j)
-           ok = 0;
-       }
+       if (pos[k] == j)
+         ok = 0;
 
       if (ok)
        {
 
       if (ok)
        {
@@ -1020,9 +778,9 @@ pack_vector (int vector)
          return j;
        }
     }
          return j;
        }
     }
-
-  berror ("pack_vector");
-  return 0;                    /* JF keep lint happy */
+#define pack_vector_succeeded 0
+  assert (pack_vector_succeeded);
+  return 0;
 }
 
 
 }
 
 
@@ -1062,10 +820,8 @@ pack_table (void)
 
   for (i = 0; i < nvectors; i++)
     {
 
   for (i = 0; i < nvectors; i++)
     {
-      if (froms[i])
-       XFREE (froms[i]);
-      if (tos[i])
-       XFREE (tos[i]);
+      XFREE (froms[i]);
+      XFREE (tos[i]);
     }
 
   XFREE (froms);
     }
 
   XFREE (froms);
@@ -1079,13 +835,15 @@ pack_table (void)
 static void
 output_base (void)
 {
 static void
 output_base (void)
 {
-  output_short_table (&table_obstack, NULL, "yypact", base,
-                     base[0], 1, nstates);
+  /* Output pact. */
+  output_table_data (&format_obstack, base,
+                    base[0], 1, nstates);
+  muscle_insert ("pact", obstack_finish (&format_obstack));
 
 
-  obstack_1grow (&table_obstack, '\n');
-
-  output_short_table (&table_obstack, NULL, "yypgoto", base,
-                     base[nstates], nstates + 1, nvectors);
+  /* Output pgoto. */
+  output_table_data (&format_obstack, base,
+                    base[nstates], nstates + 1, nvectors);
+  muscle_insert ("pgoto", obstack_finish (&format_obstack));
 
   XFREE (base);
 }
 
   XFREE (base);
 }
@@ -1094,9 +852,9 @@ output_base (void)
 static void
 output_table (void)
 {
 static void
 output_table (void)
 {
-  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);
+  output_table_data (&format_obstack, table,
+                    table[0], 1, high + 1);
+  muscle_insert ("table", obstack_finish (&format_obstack));
   XFREE (table);
 }
 
   XFREE (table);
 }
 
@@ -1104,8 +862,9 @@ output_table (void)
 static void
 output_check (void)
 {
 static void
 output_check (void)
 {
-  output_short_table (&table_obstack, NULL, "yycheck", check,
-                     check[0], 1, high + 1);
+  output_table_data (&format_obstack, check,
+                    check[0], 1, high + 1);
+  muscle_insert ("check", obstack_finish (&format_obstack));
   XFREE (check);
 }
 
   XFREE (check);
 }
 
@@ -1115,6 +874,7 @@ output_check (void)
 static void
 output_actions (void)
 {
 static void
 output_actions (void)
 {
+  int i;
   nvectors = nstates + nvars;
 
   froms = XCALLOC (short *, nvectors);
   nvectors = nstates + nvars;
 
   froms = XCALLOC (short *, nvectors);
@@ -1123,12 +883,8 @@ output_actions (void)
   width = XCALLOC (short, nvectors);
 
   token_actions ();
   width = XCALLOC (short, nvectors);
 
   token_actions ();
-  free_shifts ();
-  free_reductions ();
-  XFREE (lookaheads);
   XFREE (LA);
   XFREE (LAruleno);
   XFREE (LA);
   XFREE (LAruleno);
-  XFREE (accessing_symbol);
 
   goto_actions ();
   XFREE (goto_map + ntokens);
 
   goto_actions ();
   XFREE (goto_map + ntokens);
@@ -1137,29 +893,102 @@ output_actions (void)
 
   sort_actions ();
   pack_table ();
 
   sort_actions ();
   pack_table ();
-  obstack_1grow (&table_obstack, '\n');
+
   output_base ();
   output_table ();
   output_base ();
   output_table ();
-  obstack_1grow (&table_obstack, '\n');
+
   output_check ();
   output_check ();
+
+  for (i = 0; i < nstates; ++i)
+    {
+      free (state_table[i]->shifts);
+      XFREE (state_table[i]->reductions);
+      free (state_table[i]->errs);
+      free (state_table[i]);
+    }
+  XFREE (state_table);
 }
 
 }
 
-/*------------------------------------------.
-| Copy the parser code into TABLE_OBSTACK.  |
-`------------------------------------------*/
+\f
+/*------------------------------------------------------------.
+| Copy the parser code from SKEL_FILENAME into OOUT obstack.  |
+| and do the muscle substitution.                             |
+`------------------------------------------------------------*/
 
 static void
 
 static void
-output_parser (void)
+output_parser (const char *skel_filename, FILE *out)
 {
   int c;
   FILE *fskel;
 {
   int c;
   FILE *fskel;
-  size_t line;
-  int actions_dumped = 0;
+  size_t output_line;
+  size_t skeleton_line;
+
+  fskel = xfopen (skel_filename, "r");
+
+  /* New output code.  */
+  output_line = 1;
+  skeleton_line = 1;
+  c = getc (fskel);
+  while (c != EOF)
+    {
+      if (c != '%')
+       {
+         if (c == '\n')
+           {
+             ++output_line;
+             ++skeleton_line;
+           }
+         putc (c, out);
+         c = getc (fskel);
+       }
+      else if ((c = getc (fskel)) == '%')
+       {
+         /* Read the muscle.  */
+         const char *muscle_key = 0;
+         const char *muscle_value = 0;
+
+         while (isalnum (c = getc (fskel)) || c == '-')
+           obstack_1grow (&muscle_obstack, c);
+         obstack_1grow (&muscle_obstack, 0);
+
+         /* Output the right value, or see if it's something special.  */
+         muscle_key = obstack_finish (&muscle_obstack);
+         muscle_value = muscle_find (muscle_key);
+         if (!strcmp (muscle_key, "actions"))
+           actions_output (out, &output_line);
+         else if (!strcmp (muscle_key, "guards"))
+           guards_output (out, &output_line);
+         else if (!strcmp (muscle_key, "line"))
+           fprintf (out, "%d", output_line);
+         else if (!strcmp (muscle_key, "skeleton-line"))
+           fprintf (out, "%d", skeleton_line);
+         else if (muscle_value)
+           {
+             fputs (muscle_value, out);
+             output_line += get_lines_number (muscle_value);
+           }
+         else
+           {
+             fputs ("%%", out);
+             fputs (muscle_key, out);
+           }
+       }
+      else
+       putc ('%', out);
+    }
+
+  /* End.  */
+  xfclose (fskel);
+}
 
 
-  if (pure_parser)
-    obstack_sgrow (&table_obstack, "#define YYPURE 1\n\n");
+/*----------------------------------------.
+| Prepare the master parser to be output  |
+`----------------------------------------*/
 
 
-  /* Loop over lines in the standard parser file.  */
+static void
+output_master_parser (void)
+{
+  FILE *parser = xfopen (parser_file_name, "w");
   if (!skeleton)
     {
       if (semantic_parser)
   if (!skeleton)
     {
       if (semantic_parser)
@@ -1167,145 +996,97 @@ output_parser (void)
       else
        skeleton = skeleton_find ("BISON_SIMPLE", BISON_SIMPLE);
     }
       else
        skeleton = skeleton_find ("BISON_SIMPLE", BISON_SIMPLE);
     }
-  fskel = xfopen (skeleton, "r");
+  muscle_insert ("skeleton", skeleton);
+  muscle_insert ("parser-file-name", parser_file_name);
 
 
-  /* 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;
+  output_parser (skeleton, parser);
+  xfclose (parser);
+}
 
 
-  while (1)
-    {
-      enum line_type_e
-       {
-         regular_line,
-         sync_line,    /* #line. */
-         actions_line  /* %% actions. */
-       };
-      enum line_type_e line_type = regular_line;
 
 
-      c = getc (fskel);
+/* FIXME. */
 
 
-      /* 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
-                         obstack_sgrow (&table_obstack, "%% actio");
-                     else
-                       obstack_sgrow (&table_obstack, "%% acti");
-                   else
-                     obstack_sgrow (&table_obstack, "%% act");
-                 else
-                   obstack_sgrow (&table_obstack, "%% ac");
-               else
-                 obstack_sgrow (&table_obstack, "%% a");
-             else
-               obstack_sgrow (&table_obstack, "%% ");
-           else
-             obstack_sgrow (&table_obstack, "%%");
-         else
-           obstack_sgrow (&table_obstack, "%");
-       }
+#define MUSCLE_INSERT_INT(Key, Value)                          \
+{                                                              \
+  obstack_fgrow1 (&muscle_obstack, "%d", Value);               \
+  obstack_1grow (&muscle_obstack, 0);                          \
+  muscle_insert (Key, obstack_finish (&muscle_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));
-
-         /* Skip the end of line. */
-         for (; c != '\n' && c != EOF; c = getc (fskel))
-           /* nothing */;
-         break;
-
-       case actions_line:
-         {
-           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);
-       }
+#define MUSCLE_INSERT_STRING(Key, Value)                       \
+{                                                              \
+  obstack_sgrow (&muscle_obstack, Value);                      \
+  obstack_1grow (&muscle_obstack, 0);                          \
+  muscle_insert (Key, obstack_finish (&muscle_obstack));       \
+}
 
 
-      if (c == EOF)
-       break;
-      obstack_1grow (&table_obstack, c);
-      line++;
-    }
-  assert (actions_dumped == 1);
-  xfclose (fskel);
+#define MUSCLE_INSERT_PREFIX(Key, Value)                               \
+{                                                                      \
+  obstack_fgrow2 (&muscle_obstack, "%s%s", spec_name_prefix, Value);   \
+  obstack_1grow (&muscle_obstack, 0);                                  \
+  muscle_insert (Key, obstack_finish (&muscle_obstack));               \
 }
 
 static void
 }
 
 static void
-output_program (void)
+prepare (void)
 {
 {
-  int c;
-
-  if (!no_lines_flag)
-    obstack_fgrow2 (&table_obstack, "#line %d %s\n",
-                   lineno, quotearg_style (c_quoting_style, infile));
-
-  while ((c = getc (finput)) != EOF)
-    obstack_1grow (&table_obstack, c);
+  MUSCLE_INSERT_INT ("last", high);
+  MUSCLE_INSERT_INT ("flag", MINSHORT);
+  MUSCLE_INSERT_INT ("pure", pure_parser);
+  MUSCLE_INSERT_INT ("nsym", nsyms);
+  MUSCLE_INSERT_INT ("debug", debug_flag);
+  MUSCLE_INSERT_INT ("final", final_state);
+  MUSCLE_INSERT_INT ("maxtok", max_user_token_number);
+  MUSCLE_INSERT_INT ("error-verbose", error_verbose);
+  MUSCLE_INSERT_STRING ("prefix", spec_name_prefix);
+
+  MUSCLE_INSERT_INT ("nnts", nvars);
+  MUSCLE_INSERT_INT ("nrules", nrules);
+  MUSCLE_INSERT_INT ("nstates", nstates);
+  MUSCLE_INSERT_INT ("ntokens", ntokens);
+
+  MUSCLE_INSERT_INT ("locations-flag", locations_flag);
 }
 
 
 }
 
 
+/*-------------------------.
+| Output the header file.  |
+`-------------------------*/
+
 static void
 static void
-free_itemsets (void)
+header_output (void)
 {
 {
-  core *cp, *cptmp;
-
-  XFREE (state_table);
-
-  for (cp = first_state; cp; cp = cptmp)
+  FILE *out = xfopen (spec_defines_file, "w");
+  char *macro_name = compute_header_macro ();
+
+  fprintf (out, "#ifndef %s\n", macro_name);
+  fprintf (out, "# define %s\n\n", macro_name);
+
+  fputs (muscle_find ("tokendef"), out);
+  fprintf (out, "\
+#ifndef YYSTYPE\n\
+typedef %s
+yystype;\n\
+# define YYSTYPE yystype\n\
+#endif\n",
+                   muscle_find ("stype"));
+
+  if (!pure_parser)
+    fprintf (out, "\nextern YYSTYPE %slval;\n",
+            spec_name_prefix);
+  if (semantic_parser)
     {
     {
-      cptmp = cp->next;
-      XFREE (cp);
+      int i;
+
+      for (i = ntokens; i < nsyms; i++)
+       /* don't make these for dummy nonterminals made by gensym.  */
+       if (*tags[i] != '@')
+         fprintf (out, "# define NT%s\t%d\n", tags[i], i);
     }
     }
+
+  fprintf (out, "\n#endif /* not %s */\n", macro_name);
+  free (macro_name);
+  xfclose (out);
 }
 
 
 }
 
 
@@ -1316,51 +1097,32 @@ free_itemsets (void)
 void
 output (void)
 {
 void
 output (void)
 {
-  /* output_token_defines(ftable);      / * JF put out token defines FIRST */
+  obstack_init (&format_obstack);
 
 
-  /* If using a simple parser the definition of YYSTYPE are put into
-     TABLE_OBSTACK.  */
-  if (!semantic_parser)
-    {
-      size_t size = obstack_object_size (&attrs_obstack);
-      obstack_grow (&table_obstack, obstack_finish (&attrs_obstack), size);
-    }
-  reader_output_yylsp (&table_obstack);
-  if (debug_flag)
-    obstack_sgrow (&table_obstack, "\
-#ifndef YYDEBUG\n\
-# define YYDEBUG 1\n\
-#endif\n\
-\n");
-
-  if (semantic_parser)
-    obstack_fgrow1 (&table_obstack, "#include %s\n",
-                   quotearg_style (c_quoting_style, attrsfile));
-
-  if (!no_parser_flag)
-    obstack_sgrow (&table_obstack, "#include <stdio.h>\n\n");
-
-  /* Make "const" do nothing if not in ANSI C.  */
-  obstack_sgrow (&table_obstack, "\
-#ifndef __cplusplus\n\
-# ifndef __STDC__\n\
-#  define const\n\
-# endif\n\
-#endif\n\
-\n");
-
-  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 ();
   XFREE (ritem);
   if (semantic_parser)
     output_stos ();
   output_rule_data ();
+  XFREE (user_toknums);
   output_actions ();
   output_actions ();
-  if (!no_parser_flag)
-    output_parser ();
-  output_program ();
+
+  prepare ();
+  /* Copy definitions in directive.  */
+  obstack_1grow (&attrs_obstack, 0);
+  muscle_insert ("prologue", obstack_finish (&attrs_obstack));
+
+  /* Output the parser. */
+  output_master_parser ();
+  /* Output the header if needed. */
+  if (defines_flag)
+    header_output ();
+
+  free (rule_table + 1);
+  obstack_free (&muscle_obstack, NULL);
+  obstack_free (&format_obstack, NULL);
+  obstack_free (&action_obstack, NULL);
+  obstack_free (&attrs_obstack, NULL);
 }
 }