]> git.saurik.com Git - bison.git/blobdiff - src/output.c
* src/files.c (output_files): Free the output_obstack.
[bison.git] / src / output.c
index a5a0a606ec84bdc0dfa5051fd141f8a165398d7c..841ebe4f3780ec728f52920f437e27ad88a93f45 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;
+struct obstack output_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;
+    }   
+  
+  return lines;
+}
 
 
-  if (comment)
-    obstack_fgrow1 (oout, "/* %s. */\n", comment);
 
 
-  obstack_fgrow3 (oout, "static const %s %s[] =\n{\n  %6d",
-                 type, table_name, first_value);
+/* FIXME. */
 
 
-  j = 1;
-  for (i = begin; i < end; i++)
+static inline void
+output_table_data (struct obstack *oout,
+                  short *table_data,
+                  short first,
+                  short begin,
+                  short 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)
        {
       if (j >= 10)
        {
-         obstack_grow_string (oout, "\n  ");
+         obstack_sgrow (oout, "\n  ");
          j = 1;
        }
       else
          j = 1;
        }
       else
-       {
-         j++;
-       }
-
-      obstack_fgrow1 (oout, "%6d", short_table[i]);
-    }
-
-  obstack_grow_string (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 = quotearg_style (c_quoting_style, attrsfile);
-
-  if (semantic_parser)
-    obstack_fgrow1 (&guard_obstack, GUARDSTR, attrsfile_quoted);
-
-  if (no_parser_flag)
-    return;
-
-  if (semantic_parser)
-    obstack_fgrow1 (&action_obstack, ACTSTR, attrsfile_quoted);
-  else
-    obstack_grow_string (&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_grow_string (&guard_obstack, "\n    }\n}\n");
-
-  obstack_1grow (&action_obstack, '\n');
-
-  if (no_parser_flag)
-    return;
-
-  if (semantic_parser)
-    obstack_grow_string (&action_obstack, "    }\n");
-
-  obstack_grow_string (&action_obstack, "}\n");
-}
-
-
-
 static void
 output_token_translations (void)
 {
 static void
 output_token_translations (void)
 {
-  obstack_grow_string (&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_grow_string (&table_obstack,
-                          "\n#define YYTRANSLATE(x) (x)\n");
-    }
+  output_table_data (&output_obstack, token_translations,
+                    0, 1, max_user_token_number + 1);
+  muscle_insert ("translate", obstack_finish (&output_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_grow_string (&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 (&output_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 (&output_obstack));
 
   {
     size_t yyrhs_size = 1;
 
   {
     size_t yyrhs_size = 1;
@@ -333,21 +208,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 (&output_obstack, yyrhs,
+                      ritem[0], 1, yyrhs_size);
+    muscle_insert ("rhs", obstack_finish (&output_obstack));
+
     XFREE (yyrhs);
   }
     XFREE (yyrhs);
   }
-
-  if (!semantic_parser && !no_parser_flag)
-    obstack_grow_string (&table_obstack, "\n#endif\n");
+  
+#if 0
+  if (!semantic_parser)
+    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 (&output_obstack, values,
+                    0, 1, nstates);
+  muscle_insert ("stos", obstack_finish (&output_obstack));
 }
 
 
 }
 
 
@@ -358,130 +242,72 @@ output_rule_data (void)
   int j;
   short *short_tab = NULL;
 
   int j;
   short *short_tab = NULL;
 
-  obstack_grow_string (&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_grow_string (&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 (&output_obstack, values,
+                      0, 1, nrules + 1);
+    muscle_insert ("rline", obstack_finish (&output_obstack));
+    XFREE (values);
+  }
 
 
-  /* Output the table of symbol names.  */
-  if (!token_table_flag && !no_parser_flag)
-    obstack_grow_string (&table_obstack,
-                        "\n#if YYDEBUG != 0 || defined YYERROR_VERBOSE\n\n");
-  obstack_grow_string (&table_obstack, "\
-/* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */\n");
-  obstack_grow_string (&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_grow_string (&table_obstack, "\n  ");
+         obstack_sgrow (&output_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_grow_string (&table_obstack, "\\n");
-         else if (*p == '\t')
-           obstack_grow_string (&table_obstack, "\\t");
-         else if (*p == '\b')
-           obstack_grow_string (&table_obstack, "\\b");
-         else if (*p < 040 || *p >= 0177)
-           obstack_fgrow1 (&table_obstack, "\\%03o", *p);
-         else
-           obstack_1grow (&table_obstack, *p);
-       }
-
-      obstack_grow_string (&table_obstack, "\", ");
+      obstack_sgrow (&output_obstack, cp);
+      obstack_sgrow (&output_obstack, ", ");
       j += strsize;
     }
   /* add a NULL entry to list of tokens */
       j += strsize;
     }
   /* add a NULL entry to list of tokens */
-  obstack_grow_string (&table_obstack, "NULL\n};\n");
+  obstack_sgrow (&output_obstack, "NULL");
 
 
-  if (!token_table_flag && !no_parser_flag)
-    obstack_grow_string (&table_obstack, "#endif\n\n");
+  /* Finish table and store. */
+  obstack_1grow (&output_obstack, 0);
+  muscle_insert ("tname", obstack_finish (&output_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 (&output_obstack, user_toknums,
+                    0, 1, ntokens + 1);
+  muscle_insert ("toknum", obstack_finish (&output_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 (&output_obstack, values,
+                      0, 1, nrules + 1);
+    muscle_insert ("r1", obstack_finish (&output_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 (&output_obstack, short_tab,
+                    0, 1, nrules + 1);
+  muscle_insert ("r2", obstack_finish (&output_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      |
@@ -504,15 +330,11 @@ action_row (int state)
   int k;
   int m = 0;
   int n = 0;
   int k;
   int m = 0;
   int n = 0;
-  int count;
   int default_rule;
   int nreds;
   int default_rule;
   int nreds;
-  int max;
   int rule;
   int shift_state;
   int symbol;
   int rule;
   int shift_state;
   int symbol;
-  unsigned mask;
-  unsigned *wordp;
   reductions *redp;
   shifts *shiftp;
   errs *errp;
   reductions *redp;
   shifts *shiftp;
   errs *errp;
@@ -523,7 +345,7 @@ action_row (int state)
 
   default_rule = 0;
   nreds = 0;
 
   default_rule = 0;
   nreds = 0;
-  redp = reduction_table[state];
+  redp = state_table[state]->reductions;
 
   if (redp)
     {
 
   if (redp)
     {
@@ -533,69 +355,46 @@ action_row (int state)
        {
          /* loop over all the rules available here which require
             lookahead */
        {
          /* loop over all the rules available here which require
             lookahead */
-         m = lookaheads[state];
-         n = lookaheads[state + 1];
+         m = state_table[state]->lookaheads;
+         n = state_table[state + 1]->lookaheads;
 
          for (i = n - 1; i >= m; i--)
 
          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++;
-                   }
-               }
-           }
+           /* 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 (i), j))
+               actrow[j] = -LAruleno[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)
+  shiftp = state_table[state]->shifts;
+  for (i = 0; i < shiftp->nshifts; i++)
     {
     {
-      k = shiftp->nshifts;
-
-      for (i = 0; i < k; i++)
-       {
-         shift_state = shiftp->shifts[i];
-         if (!shift_state)
-           continue;
+      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.  */
+  errp = state_table[state]->errs;
 
   if (errp)
     {
 
   if (errp)
     {
@@ -613,14 +412,14 @@ action_row (int state)
 
   if (nreds >= 1 && !nodefault)
     {
 
   if (nreds >= 1 && !nodefault)
     {
-      if (consistent[state])
+      if (state_table[state]->consistent)
        default_rule = redp->rules[0];
       else
        {
        default_rule = redp->rules[0];
       else
        {
-         max = 0;
+         int max = 0;
          for (i = m; i < n; i++)
            {
          for (i = m; i < n; i++)
            {
-             count = 0;
+             int count = 0;
              rule = -LAruleno[i];
 
              for (j = 0; j < ntokens; j++)
              rule = -LAruleno[i];
 
              for (j = 0; j < ntokens; j++)
@@ -722,50 +521,52 @@ token_actions (void)
       yydefact[i] = action_row (i);
       save_row (i);
     }
       yydefact[i] = action_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 (&output_obstack, yydefact,
+                    yydefact[0], 1, nstates);
+  muscle_insert ("defact", obstack_finish (&output_obstack));
+
+  XFREE (actrow);
   XFREE (yydefact);
 }
 
 
   XFREE (yydefact);
 }
 
 
-static void
-free_shifts (void)
-{
-  shifts *sp, *sptmp;  /* JF derefrenced freed ptr */
-
-  XFREE (shift_table);
-
-  for (sp = first_shift; sp; sp = sptmp)
-    {
-      sptmp = sp->next;
-      XFREE (sp);
-    }
-}
-
+/*-----------------------------.
+| Output the actions to OOUT.  |
+`-----------------------------*/
 
 static void
 
 static void
-free_reductions (void)
+actions_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].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);
+      }
 }
 
 
 }
 
 
-
 static void
 save_column (int symbol, int default_state)
 {
 static void
 save_column (int symbol, int default_state)
 {
@@ -857,10 +658,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);
@@ -868,8 +668,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 (&output_obstack, yydefgoto,
+                    yydefgoto[0], 1, nsyms - ntokens);
+  muscle_insert ("defgoto", obstack_finish (&output_obstack));
 
   XFREE (state_count);
   XFREE (yydefgoto);
 
   XFREE (state_count);
   XFREE (yydefgoto);
@@ -1013,8 +814,8 @@ pack_vector (int vector)
        }
     }
 
        }
     }
 
-  berror ("pack_vector");
-  return 0;                    /* JF keep lint happy */
+  assert (!"pack_vector");
+  return 0;
 }
 
 
 }
 
 
@@ -1071,13 +872,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);
-
-  obstack_1grow (&table_obstack, '\n');
+  /* Output pact. */
+  output_table_data (&output_obstack, base,
+                    base[0], 1, nstates);
+  muscle_insert ("pact", obstack_finish (&output_obstack));
 
 
-  output_short_table (&table_obstack, NULL, "yypgoto", base,
-                     base[nstates], nstates + 1, nvectors);
+  /* Output pgoto. */
+  output_table_data (&output_obstack, base,
+                    base[nstates], nstates + 1, nvectors);
+  muscle_insert ("pgoto", obstack_finish (&output_obstack));
 
   XFREE (base);
 }
 
   XFREE (base);
 }
@@ -1086,9 +889,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 (&output_obstack, table,
+                    table[0], 1, high + 1);
+  muscle_insert ("table", obstack_finish (&output_obstack));
   XFREE (table);
 }
 
   XFREE (table);
 }
 
@@ -1096,8 +899,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 (&output_obstack, check,
+                    check[0], 1, high + 1);
+  muscle_insert ("check", obstack_finish (&output_obstack));
   XFREE (check);
 }
 
   XFREE (check);
 }
 
@@ -1107,6 +911,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);
@@ -1115,12 +920,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);
@@ -1129,173 +930,192 @@ 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)
+    {
+      XFREE (state_table[i]->shifts);
+      XFREE (state_table[i]->reductions);
+      XFREE (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;
   size_t line;
 {
   int c;
   FILE *fskel;
   size_t line;
-  const char *skeleton = NULL;
-  int actions_dumped = 0;
 
 
-  if (pure_parser)
-    obstack_grow_string (&table_obstack, "#define YYPURE 1\n\n");
+  fskel = xfopen (skel_filename, "r");
 
 
-  /* Loop over lines in the standard parser file.  */
-  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)
+  /* New output code.  */
+  line = 1;
+  c = getc (fskel);
+  while (c != EOF)
     {
     {
-      enum line_type_e
-       {
-         regular_line,
-         sync_line,    /* #line. */
-         actions_line  /* %% actions. */
-       };
-      enum line_type_e line_type = regular_line;
-
-      c = getc (fskel);
-
-      /* Is this line special? */
-      if (c == '#')
+      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_grow_string (&table_obstack, "#lin");
-             else
-               obstack_grow_string (&table_obstack, "#li");
-           else
-             obstack_grow_string (&table_obstack, "#l");
-         else
-           obstack_grow_string (&table_obstack, "#");
+         if (c == '\n')
+           ++line;
+         putc (c, out);
+         c = getc (fskel);
        }
        }
-      else if (c == '%')
+      else if ((c = getc (fskel)) == '%')
        {
        {
-         /* 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_grow_string (&table_obstack, "%% action");
-                       else
-                         obstack_grow_string (&table_obstack, "%% actio");
-                     else
-                       obstack_grow_string (&table_obstack, "%% acti");
-                   else
-                     obstack_grow_string (&table_obstack, "%% act");
-                 else
-                   obstack_grow_string (&table_obstack, "%% ac");
-               else
-                 obstack_grow_string (&table_obstack, "%% a");
-             else
-               obstack_grow_string (&table_obstack, "%% ");
-           else
-             obstack_grow_string (&table_obstack, "%%");
+         /* 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, &line);
+         else if (!strcmp (muscle_key, "line"))
+           fprintf (out, "%d", line);
+         else if (muscle_value)
+           {
+             fputs (muscle_value, out);
+             line += get_lines_number (muscle_value);
+           }     
          else
          else
-           obstack_grow_string (&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));
-
-         /* 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);
+           {
+             fputs ("%%", out);
+             fputs (muscle_key, out);
+           }
        }
        }
-
-      if (c == EOF)
-       break;
-      obstack_1grow (&table_obstack, c);
-      line++;
+      else
+       putc ('%', out);
     }
     }
-  assert (actions_dumped == 1);
+
+  /* End.  */
   xfclose (fskel);
 }
 
   xfclose (fskel);
 }
 
+/*----------------------------------------.
+| Prepare the master parser to be output  |
+`----------------------------------------*/
+
 static void
 static void
-output_program (void)
+output_master_parser (void)
 {
 {
-  int c;
+  FILE *parser = xfopen (parser_file_name, "w");
+  if (!skeleton)
+    {
+      if (semantic_parser)
+       skeleton = skeleton_find ("BISON_HAIRY", BISON_HAIRY);
+      else
+       skeleton = skeleton_find ("BISON_SIMPLE", BISON_SIMPLE);
+    }
+  muscle_insert ("skeleton", skeleton);
+  muscle_insert ("parser-file-name", parser_file_name);
 
 
-  if (!no_lines_flag)
-    obstack_fgrow2 (&table_obstack, "#line %d %s\n",
-                   lineno, quotearg_style (c_quoting_style, infile));
+  output_parser (skeleton, parser);
+  xfclose (parser);
+}
+
+
+/* FIXME. */
 
 
-  while ((c = getc (finput)) != EOF)
-    obstack_1grow (&table_obstack, c);
+#define MUSCLE_INSERT_INT(Key, Value)                          \
+{                                                              \
+  obstack_fgrow1 (&muscle_obstack, "%d", Value);               \
+  obstack_1grow (&muscle_obstack, 0);                          \
+  muscle_insert (Key, obstack_finish (&muscle_obstack));       \
 }
 
 }
 
+#define MUSCLE_INSERT_STRING(Key, Value)                       \
+{                                                              \
+  obstack_sgrow (&muscle_obstack, Value);                      \
+  obstack_1grow (&muscle_obstack, 0);                          \
+  muscle_insert (Key, obstack_finish (&muscle_obstack));       \
+}
+
+#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
-free_itemsets (void)
+prepare (void)
 {
 {
-  core *cp, *cptmp;
+  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 ("ntbase", ntokens);
+  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);
+}
 
 
-  XFREE (state_table);
 
 
-  for (cp = first_state; cp; cp = cptmp)
+/*-------------------------.
+| Output the header file.  |
+`-------------------------*/
+
+static void
+header_output (void)
+{
+  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\tNT%s\t%d\n", tags[i], i);
     }
     }
+
+  fprintf (out, "\n#endif /* not %s */\n", macro_name);
+  free (macro_name);
+  xfclose (out);
 }
 
 
 }
 
 
@@ -1306,51 +1126,31 @@ free_itemsets (void)
 void
 output (void)
 {
 void
 output (void)
 {
-  /* output_token_defines(ftable);      / * JF put out token defines FIRST */
-
-  /* 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_grow_string (&table_obstack, "\
-#ifndef YYDEBUG\n\
-# define YYDEBUG 1\n\
-#endif\n\
-\n");
+  obstack_init (&output_obstack);
 
 
-  if (semantic_parser)
-    obstack_fgrow1 (&table_obstack, "#include %s\n",
-                   quotearg_style (c_quoting_style, attrsfile));
-
-  if (!no_parser_flag)
-    obstack_grow_string (&table_obstack, "#include <stdio.h>\n\n");
-
-  /* Make "const" do nothing if not in ANSI C.  */
-  obstack_grow_string (&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, 0);
+  obstack_free (&output_obstack, 0);
+  obstack_free (&action_obstack, 0);
 }
 }