]> git.saurik.com Git - bison.git/blobdiff - src/output.c
* src/output.c (output, prepare): Make sure the values of the
[bison.git] / src / output.c
index f7e218801f844286049aafadb7112a82fca764dd..dbcfbf0119924a480af72a8880bde8d765f84c92 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.
 
    02111-1307, USA.  */
 
 
    02111-1307, USA.  */
 
 
-/* functions to output parsing data to various files.  Entries are:
+/* The parser tables consist of these tables.
+   Starred ones needed only for the semantic parser.
+   Double starred are output only if switches are set.
 
 
-  output_headers ()
+   yytranslate = vector mapping yylex's token numbers into bison's token
+   numbers.
 
 
-Output constant strings to the beginning of certain files.
+   ** yytname = vector of string-names indexed by bison token number
 
 
-  output_trailers()
+   ** yytoknum = vector of yylex token numbers corresponding to entries
+   in yytname
 
 
-Output constant strings to the ends of certain files.
+   yyrline = vector of line-numbers of all rules.  For yydebug printouts.
 
 
-  output ()
+   yyrhs = vector of items of all rules.
+   This is exactly what ritems contains.  For yydebug and for semantic
+   parser.
 
 
-Output the parsing tables and the parser code to ftable.
+   yyprhs[r] = index in yyrhs of first item for rule r.
 
 
-The parser tables consist of these tables.
-Starred ones needed only for the semantic parser.
-Double starred are output only if switches are set.
+   yyr1[r] = symbol number of symbol that rule r derives.
 
 
-yytranslate = vector mapping yylex's token numbers into bison's token numbers.
+   yyr2[r] = number of symbols composing right hand side of rule r.
 
 
-** yytname = vector of string-names indexed by bison token number
+   * yystos[s] = the symbol number of the symbol that leads to state s.
 
 
-** yytoknum = vector of yylex token numbers corresponding to entries in yytname
+   yydefact[s] = default rule to reduce with in state s,
+   when yytable doesn't specify something else to do.
+   Zero means the default is an error.
 
 
-yyrline = vector of line-numbers of all rules.  For yydebug printouts.
+   yydefgoto[i] = default state to go to after a reduction of a rule that
+   generates variable ntokens + i, except when yytable
+   specifies something else to do.
 
 
-yyrhs = vector of items of all rules.
-        This is exactly what ritems contains.  For yydebug and for semantic
-       parser.
+   yypact[s] = index in yytable of the portion describing state s.
+   The lookahead token's type is used to index that portion
+   to find out what to do.
 
 
-yyprhs[r] = index in yyrhs of first item for rule r.
+   If the value in yytable is positive,
+   we shift the token and go to that state.
 
 
-yyr1[r] = symbol number of symbol that rule r derives.
+   If the value is negative, it is minus a rule number to reduce by.
 
 
-yyr2[r] = number of symbols composing right hand side of rule r.
+   If the value is zero, the default action from yydefact[s] is used.
 
 
-* yystos[s] = the symbol number of the symbol that leads to state s.
+   yypgoto[i] = the index in yytable of the portion describing
+   what to do after reducing a rule that derives variable i + ntokens.
+   This portion is indexed by the parser state number, s,
+   as of before the text for this nonterminal was read.
+   The value from yytable is the state to go to if
+   the corresponding value in yycheck is s.
 
 
-yydefact[s] = default rule to reduce with in state s,
-             when yytable doesn't specify something else to do.
-             Zero means the default is an error.
+   yytable = a vector filled with portions for different uses,
+   found via yypact and yypgoto.
 
 
-yydefgoto[i] = default state to go to after a reduction of a rule that
-              generates variable ntokens + i, except when yytable
-              specifies something else to do.
+   yycheck = a vector indexed in parallel with yytable.
+   It indicates, in a roundabout way, the bounds of the
+   portion you are trying to examine.
 
 
-yypact[s] = index in yytable of the portion describing state s.
-            The lookahead token's type is used to index that portion
-            to find out what to do.
-
-           If the value in yytable is positive,
-           we shift the token and go to that state.
-
-           If the value is negative, it is minus a rule number to reduce by.
-
-           If the value is zero, the default action from yydefact[s] is used.
-
-yypgoto[i] = the index in yytable of the portion describing
-             what to do after reducing a rule that derives variable i + ntokens.
-             This portion is indexed by the parser state number, s,
-            as of before the text for this nonterminal was read.
-            The value from yytable is the state to go to if
-             the corresponding value in yycheck is s.
-
-yytable = a vector filled with portions for different uses,
-          found via yypact and yypgoto.
-
-yycheck = a vector indexed in parallel with yytable.
-         It indicates, in a roundabout way, the bounds of the
-         portion you are trying to examine.
-
-         Suppose that the portion of yytable starts at index p
-         and the index to be examined within the portion is i.
-         Then if yycheck[p+i] != i, i is outside the bounds
-         of what is actually allocated, and the default
-         (from yydefact or yydefgoto) should be used.
-         Otherwise, yytable[p+i] should be used.
-
-YYFINAL = the state number of the termination state.
-YYFLAG = most negative short int.  Used to flag ??
-YYNTBASE = ntokens.
+   Suppose that the portion of yytable starts at index p
+   and the index to be examined within the portion is i.
+   Then if yycheck[p+i] != i, i is outside the bounds
+   of what is actually allocated, and the default
+   (from yydefact or yydefgoto) should be used.
+   Otherwise, yytable[p+i] should be used.
 
 
+   YYFINAL = the state number of the termination state.
+   YYFLAG = most negative short int.  Used to flag ??
+   YYNTBASE = ntokens.
 */
 
 */
 
-#include <stdio.h>
 #include "system.h"
 #include "system.h"
-#include "machine.h"
-#include "alloc.h"
+#include "obstack.h"
+#include "quotearg.h"
+#include "getargs.h"
 #include "files.h"
 #include "gram.h"
 #include "files.h"
 #include "gram.h"
-#include "state.h"
+#include "LR0.h"
 #include "complain.h"
 #include "complain.h"
+#include "output.h"
+#include "lalr.h"
+#include "reader.h"
+#include "conflicts.h"
+#include "muscle_tab.h"
 
 
 
 
-extern int debugflag;
-extern int nolinesflag;
-extern int noparserflag;
-extern int toknumflag;
-
-extern char **tags;
-extern int *user_toknums;
-extern int tokensetsize;
-extern int final_state;
-extern core **state_table;
-extern shifts **shift_table;
-extern errs **err_table;
-extern reductions **reduction_table;
-extern short *accessing_symbol;
-extern unsigned *LA;
-extern short *LAruleno;
-extern short *lookaheads;
-extern char *consistent;
-extern short *goto_map;
-extern short *from_state;
-extern short *to_state;
-
-void output_headers PARAMS((void));
-void output_trailers PARAMS((void));
-void output PARAMS((void));
-void output_token_translations PARAMS((void));
-void output_gram PARAMS((void));
-void output_stos PARAMS((void));
-void output_rule_data PARAMS((void));
-void output_defines PARAMS((void));
-void output_actions PARAMS((void));
-void token_actions PARAMS((void));
-void save_row PARAMS((int));
-void goto_actions PARAMS((void));
-void save_column PARAMS((int, int));
-void sort_actions PARAMS((void));
-void pack_table PARAMS((void));
-void output_base PARAMS((void));
-void output_table PARAMS((void));
-void output_check PARAMS((void));
-void output_parser PARAMS((void));
-void output_program PARAMS((void));
-void free_shifts PARAMS((void));
-void free_reductions PARAMS((void));
-void free_itemsets PARAMS((void));
-int action_row PARAMS((int));
-int default_goto PARAMS((int));
-int matching_state PARAMS((int));
-int pack_vector PARAMS((int));
-
-extern void berror PARAMS((char *));
-extern void reader_output_yylsp PARAMS((FILE *));
-
 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;
 
 
-#define        GUARDSTR        "\n#include \"%s\"\nextern int yyerror;\n\
-extern int yycost;\nextern char * yymsg;\nextern YYSTYPE yyval;\n\n\
-yyguard(n, yyvsp, yylsp)\nregister int n;\nregister YYSTYPE *yyvsp;\n\
-register YYLTYPE *yylsp;\n\
-{\n  yyerror = 0;\nyycost = 0;\n  yymsg = 0;\nswitch (n)\n    {"
-
-#define        ACTSTR          "\n#include \"%s\"\nextern YYSTYPE yyval;\
-\nextern int yychar;\
-yyaction(n, yyvsp, yylsp)\nregister int n;\nregister 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);
-    }
-}
-
-
-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");
-}
-
+/* FIXME. */
 
 
-void
-output (void)
+static inline void
+output_table_data (struct obstack *oout,
+                  short *table_data,
+                  short first,
+                  short begin,
+                  short end)
 {
 {
-  int c;
+  int i;
+  int j = 1;
 
 
-  /* output_token_defines(ftable);     / * JF put out token defines FIRST */
-  if (!semantic_parser)                /* JF Put out other stuff */
+  obstack_fgrow1 (oout, "%6d", first);
+  for (i = begin; i < end; ++i)
     {
     {
-      rewind(fattrs);
-      while ((c=getc(fattrs))!=EOF)
-        putc(c,ftable);
+      obstack_1grow (oout, ',');
+      if (j >= 10)
+       {
+         obstack_sgrow (oout, "\n  ");
+         j = 1;
+       }
+      else
+       ++j;
+      obstack_fgrow1 (oout, "%6d", table_data[i]);
     }
     }
-  reader_output_yylsp(ftable);
-  if (debugflag)
-    fprintf(ftable, "#ifndef YYDEBUG\n#define YYDEBUG %d\n#endif\n\n",
-           !!debugflag);
-
-  if (semantic_parser)
-    fprintf(ftable, "#include \"%s\"\n", attrsfile);
-
-  if (! noparserflag)
-    fprintf(ftable, "#include <stdio.h>\n\n");
-
-  /* Make "const" do nothing if not in ANSI C.  */
-  fprintf (ftable, "#ifndef __cplusplus\n#ifndef __STDC__\n#define const\n#endif\n#endif\n\n");
-
-  free_itemsets();
-  output_defines();
-  output_token_translations();
-/*   if (semantic_parser) */
-  /* This is now unconditional because debugging printouts can use it.  */
-  output_gram();
-  FREE(ritem);
-  if (semantic_parser)
-    output_stos();
-  output_rule_data();
-  output_actions();
-  if (! noparserflag)
-    output_parser();
-  output_program();
+  obstack_1grow (oout, 0);
 }
 
 
 }
 
 
-void
+static void
 output_token_translations (void)
 {
 output_token_translations (void)
 {
-  register int i, j;
-/*   register 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);
+  muscle_insert ("translate", obstack_finish (&output_obstack));
+  XFREE (token_translations);
 }
 
 
 }
 
 
-void
+static void
 output_gram (void)
 {
 output_gram (void)
 {
-  register int i;
-  register int j;
-  register 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");
-
-  fprintf(ftable, "\nstatic const short yyprhs[] = {     0");
-
-  j = 10;
-  for (i = 1; i <= nrules; i++)
-    {
-      putc(',', ftable);
-
-      if (j >= 10)
-       {
-         putc('\n', ftable);
-         j = 1;
-       }
-      else
-       {
-         j++;
-       }
-
-      fprintf(ftable, "%6d", rrhs[i]);
-    }
+  {
+    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);
+  }
 
 
-  fprintf(ftable, "\n};\n");
+  muscle_insert ("prhs", obstack_finish (&output_obstack));
 
 
-  fprintf(ftable, "\nstatic const short yyrhs[] = {%6d", ritem[0]);
+  {
+    size_t yyrhs_size = 1;
+    short *yyrhs, *sp;
+    int i;
 
 
-  j = 10;
-  for (sp = ritem + 1; *sp; sp++)
-    {
-      putc(',', ftable);
+    for (sp = ritem + 1; *sp; sp++)
+      ++yyrhs_size;
+    yyrhs = XMALLOC (short, yyrhs_size);
 
 
-      if (j >= 10)
-       {
-         putc('\n', ftable);
-         j = 1;
-       }
-      else
-       {
-         j++;
-       }
+    for (sp = ritem + 1, i = 1; *sp; ++sp, ++i)
+      yyrhs[i] = *sp > 0 ? *sp : 0;
 
 
-      if (*sp > 0)
-       fprintf(ftable, "%6d", *sp);
-      else
-       fprintf(ftable, "     0");
-    }
+    output_table_data (&output_obstack, yyrhs,
+                      ritem[0], 1, yyrhs_size);
+    muscle_insert ("rhs", obstack_finish (&output_obstack));
 
 
-  fprintf(ftable, "\n};\n");
+    XFREE (yyrhs);
+  }
 
 
-  if (! semantic_parser  && ! noparserflag)
-    fprintf(ftable, "\n#endif\n");
+#if 0
+  if (!semantic_parser && !no_parser_flag)
+    obstack_sgrow (&table_obstack, "\n#endif\n");
+#endif
 }
 
 
 }
 
 
-void
+static void
 output_stos (void)
 {
 output_stos (void)
 {
-  register int i;
-  register int j;
-
-  fprintf(ftable, "\nstatic const short yystos[] = {     0");
-
-  j = 10;
-  for (i = 1; i < nstates; i++)
-    {
-      putc(',', ftable);
-
-      if (j >= 10)
-       {
-         putc('\n', ftable);
-         j = 1;
-       }
-      else
-       {
-         j++;
-       }
-
-      fprintf(ftable, "%6d", accessing_symbol[i]);
-    }
-
-  fprintf(ftable, "\n};\n");
+  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));
 }
 
 
 }
 
 
-void
+static void
 output_rule_data (void)
 {
 output_rule_data (void)
 {
-  register int i;
-  register int j;
-
-  fputs ("\n\
-#if YYDEBUG != 0\n\
-/* YYRLINE[yyn]: source line where rule number YYN was defined. */\n\
-static const short yyrline[] = { 0", ftable);
-
-  j = 10;
-  for (i = 1; i <= nrules; i++)
-    {
-      putc(',', ftable);
-
-      if (j >= 10)
-       {
-         putc('\n', ftable);
-         j = 1;
-       }
-      else
-       {
-         j++;
-       }
-
-      fprintf(ftable, "%6d", rline[i]);
-    }
-  fprintf(ftable, "\n};\n#endif\n\n");
-
-  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.  */
+  int i;
+  int j;
+  short *short_tab = NULL;
+
+  {
+    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);
+  }
 
 
-  fprintf(ftable,
-          "static const char * const yytname[] = {   \"%s\"",
-          tags[0]);
 
 
-  j = strlen (tags[0]) + 44;
-  for (i = 1; i < nsyms; i++)
-               /* this used to be i<=nsyms, but that output a final "" symbol
-                       almost by accident */
+  j = 0;
+  for (i = 0; i < nsyms; i++)
+    /* this used to be i<=nsyms, but that output a final "" symbol
+       almost by accident */
     {
     {
-      register char *p;
-      putc(',', ftable);
-      j++;
+      /* Width of the next token, including the two quotes, the coma
+        and the space.  */
+      int strsize = 4;
+      char *p;
 
 
-      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);
+  muscle_insert ("tname", obstack_finish (&output_obstack));
 
   /* Output YYTOKNUM. */
 
   /* Output YYTOKNUM. */
-  if (toknumflag)
-    {
-      fprintf(ftable, "static const short yytoknum[] = { 0");
-      j = 10;
-      for (i = 1; i <= ntokens; i++) {
-          putc(',', ftable);
-          if (j >= 10)
-            {
-              putc('\n', ftable);
-              j = 1;
-            }
-          else
-            j++;
-          fprintf(ftable, "%6d", user_toknums[i]);
-      }
-      fprintf(ftable, "\n};\n\n");
-    }
+  output_table_data (&output_obstack, user_toknums,
+                    0, 1, ntokens + 1);
+  muscle_insert ("toknum", obstack_finish (&output_obstack));
 
   /* Output YYR1. */
 
   /* Output YYR1. */
-  fputs ("\
-/* YYR1[YYN]: Symbol number of symbol that rule YYN derives. */\n\
-static const short yyr1[] = {     0", ftable);
-
-  j = 10;
-  for (i = 1; i <= nrules; i++)
-    {
-      putc(',', ftable);
-
-      if (j >= 10)
-       {
-         putc('\n', ftable);
-         j = 1;
-       }
-      else
-       {
-         j++;
-       }
-
-      fprintf(ftable, "%6d", rlhs[i]);
-    }
-  FREE(rlhs + 1);
-  fputs ("\n\
-};\n\
-\n", ftable);
+  {
+    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. */
 
   /* Output YYR2. */
-  fputs ("\
-/* YYR2[YYN]: Number of symbols composing right hand side of rule YYN. */\n\
-static const short yyr2[] = {     0", ftable);
-  j = 10;
+  short_tab = XMALLOC (short, nrules + 1);
   for (i = 1; i < nrules; i++)
   for (i = 1; i < nrules; i++)
-    {
-      putc(',', ftable);
-
-      if (j >= 10)
-       {
-         putc('\n', ftable);
-         j = 1;
-       }
-      else
-       {
-         j++;
-       }
-
-      fprintf(ftable, "%6d", rrhs[i + 1] - rrhs[i] - 1);
-    }
-
-  putc(',', ftable);
-  if (j >= 10)
-    putc('\n', ftable);
-
-  fprintf(ftable, "%6d\n};\n", nitems - rrhs[nrules] - 1);
-  FREE(rrhs + 1);
-}
-
-
-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);
-}
-
-
-
-/* compute and output yydefact, yydefgoto, yypact, yypgoto, yytable and yycheck.  */
-
-void
-output_actions (void)
-{
-  nvectors = nstates + nvars;
-
-  froms = NEW2(nvectors, short *);
-  tos = NEW2(nvectors, short *);
-  tally = NEW2(nvectors, short);
-  width = NEW2(nvectors, short);
-
-  token_actions();
-  free_shifts();
-  free_reductions();
-  FREE(lookaheads);
-  FREE(LA);
-  FREE(LAruleno);
-  FREE(accessing_symbol);
-
-  goto_actions();
-  FREE(goto_map + ntokens);
-  FREE(from_state);
-  FREE(to_state);
-
-  sort_actions();
-  pack_table();
-  output_base();
-  output_table();
-  output_check();
+    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 (rule_table + 1);
 }
 
 }
 
-
-
-/* figure out the actions for the specified state, indexed by lookahead token type.
-
-   The yydefact table is output now.  The detailed info
-   is saved for putting into yytable later.  */
-
-void
-token_actions (void)
-{
-  register int i;
-  register int j;
-  register int k;
-
-  actrow = NEW2(ntokens, short);
-
-  k = action_row(0);
-  fprintf(ftable, "\nstatic const short yydefact[] = {%6d", k);
-  save_row(0);
-
-  j = 10;
-  for (i = 1; i < nstates; i++)
-    {
-      putc(',', ftable);
-
-      if (j >= 10)
-       {
-         putc('\n', ftable);
-         j = 1;
-       }
-      else
-       {
-         j++;
-       }
-
-      k = action_row(i);
-      fprintf(ftable, "%6d", k);
-      save_row(i);
-    }
-
-  fprintf(ftable, "\n};\n");
-  FREE(actrow);
-}
-
-
-
-/* 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 default action (yydefact) for the state.
-   In addition, actrow is filled with what to do for each kind of token,
-   index by symbol number, with zero meaning do the default action.
-   The value MINSHORT, a very negative number, means this situation
-   is an error.  The parser recognizes this value specially.
-
-   This is where conflicts are resolved.  The loop over lookahead rules
-   considered lower-numbered rules last, and the last rule considered that likes
-   a token gets to handle it.  */
-
-int
+/*------------------------------------------------------------------.
+| 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      |
+| default action (yydefact) for the state.  In addition, actrow is  |
+| filled with what to do for each kind of token, index by symbol    |
+| number, with zero meaning do the default action.  The value       |
+| MINSHORT, a very negative number, means this situation is an      |
+| error.  The parser recognizes this value specially.               |
+|                                                                   |
+| This is where conflicts are resolved.  The loop over lookahead    |
+| rules considered lower-numbered rules last, and the last rule     |
+| considered that likes a token gets to handle it.                  |
+`------------------------------------------------------------------*/
+
+static int
 action_row (int state)
 {
 action_row (int state)
 {
-  register int i;
-  register int j;
-  register int k;
-  register int m = 0;
-  register int n = 0;
-  register int count;
-  register int default_rule;
-  register int nreds;
-  register int max;
-  register int rule;
-  register int shift_state;
-  register int symbol;
-  register unsigned mask;
-  register unsigned *wordp;
-  register reductions *redp;
-  register shifts *shiftp;
-  register errs *errp;
-  int nodefault = 0;  /* set nonzero to inhibit having any default reduction */
+  int i;
+  int j;
+  int k;
+  int m = 0;
+  int n = 0;
+  int default_rule;
+  int nreds;
+  int rule;
+  int shift_state;
+  int symbol;
+  reductions *redp;
+  shifts *shiftp;
+  errs *errp;
+  int nodefault = 0;           /* set nonzero to inhibit having any default reduction */
 
   for (i = 0; i < ntokens; i++)
     actrow[i] = 0;
 
   default_rule = 0;
   nreds = 0;
 
   for (i = 0; i < ntokens; i++)
     actrow[i] = 0;
 
   default_rule = 0;
   nreds = 0;
-  redp = reduction_table[state];
+  redp = state_table[state]->reductions;
 
   if (redp)
     {
 
   if (redp)
     {
@@ -746,65 +363,48 @@ action_row (int state)
 
       if (nreds >= 1)
        {
 
       if (nreds >= 1)
        {
-         /* loop over all the rules available here which require lookahead */
-         m = lookaheads[state];
-         n = lookaheads[state + 1];
+         /* loop over all the rules available here which require
+            lookahead */
+         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.  */
-
-  if (shiftp)
+  /* 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.  */
+  shiftp = state_table[state]->shifts;
+  for (i = 0; i < shiftp->nshifts; i++)
     {
     {
-      k = shiftp->nshifts;
+      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 = state_table[shift_state]->accessing_symbol;
 
 
-         symbol = accessing_symbol[shift_state];
-
-         if (ISVAR(symbol))
-           break;
-
-         actrow[symbol] = shift_state;
+      if (ISVAR (symbol))
+       break;
 
 
-         /* do not use any default reduction if there is a shift for error */
+      actrow[symbol] = shift_state;
 
 
-         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)
     {
@@ -817,19 +417,20 @@ action_row (int state)
        }
     }
 
        }
     }
 
-  /* 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 (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;
-             rule = - LAruleno[i];
+             int count = 0;
+             rule = -LAruleno[i];
 
              for (j = 0; j < ntokens; j++)
                {
 
              for (j = 0; j < ntokens; j++)
                {
@@ -855,7 +456,7 @@ action_row (int state)
                    actrow[j] = 0;
                }
 
                    actrow[j] = 0;
                }
 
-             default_rule = - default_rule;
+             default_rule = -default_rule;
            }
        }
     }
            }
        }
     }
@@ -870,18 +471,18 @@ action_row (int state)
          actrow[j] = 0;
       }
 
          actrow[j] = 0;
       }
 
-  return (default_rule);
+  return default_rule;
 }
 
 
 }
 
 
-void
+static void
 save_row (int state)
 {
 save_row (int state)
 {
-  register int i;
-  register int count;
-  register short *sp;
-  register short *sp1;
-  register short *sp2;
+  int i;
+  int count;
+  short *sp;
+  short *sp1;
+  short *sp2;
 
   count = 0;
   for (i = 0; i < ntokens; i++)
 
   count = 0;
   for (i = 0; i < ntokens; i++)
@@ -893,8 +494,8 @@ save_row (int state)
   if (count == 0)
     return;
 
   if (count == 0)
     return;
 
-  froms[state] = sp1 = sp = NEW2(count, short);
-  tos[state] = sp2 = NEW2(count, short);
+  froms[state] = sp1 = sp = XCALLOC (short, count);
+  tos[state] = sp2 = XCALLOC (short, count);
 
   for (i = 0; i < ntokens; i++)
     {
 
   for (i = 0; i < ntokens; i++)
     {
@@ -910,67 +511,91 @@ save_row (int state)
 }
 
 
 }
 
 
+/*------------------------------------------------------------------.
+| Figure out the actions for the specified state, indexed by        |
+| lookahead token type.                                             |
+|                                                                   |
+| The YYDEFACT table is output now.  The detailed info is saved for |
+| putting into YYTABLE later.                                       |
+`------------------------------------------------------------------*/
+
+static void
+token_actions (void)
+{
+  int i;
+  short *yydefact = XCALLOC (short, nstates);
+
+  actrow = XCALLOC (short, ntokens);
+  for (i = 0; i < nstates; ++i)
+    {
+      yydefact[i] = action_row (i);
+      save_row (i);
+    }
+
+  output_table_data (&output_obstack, yydefact,
+                    yydefact[0], 1, nstates);
+  muscle_insert ("defact", obstack_finish (&output_obstack));
 
 
-/* figure out what to do after reducing with each rule,
-   depending on the saved state from before the beginning
-   of parsing the data that matched this rule.
+  XFREE (actrow);
+  XFREE (yydefact);
+}
 
 
-   The yydefgoto table is output now.  The detailed info
-   is saved for putting into yytable later.  */
 
 
-void
-goto_actions (void)
+static void
+save_column (int symbol, int default_state)
 {
 {
-  register int i;
-  register int j;
-  register int k;
+  int i;
+  short *sp;
+  short *sp1;
+  short *sp2;
+  int count;
+  int symno;
 
 
-  state_count = NEW2(nstates, short);
+  short begin = goto_map[symbol];
+  short end = goto_map[symbol + 1];
 
 
-  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++)
+  count = 0;
+  for (i = begin; i < end; i++)
     {
     {
-      putc(',', ftable);
+      if (to_state[i] != default_state)
+       count++;
+    }
 
 
-      if (j >= 10)
-       {
-         putc('\n', ftable);
-         j = 1;
-       }
-      else
+  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++)
+    {
+      if (to_state[i] != default_state)
        {
        {
-         j++;
+         *sp1++ = from_state[i];
+         *sp2++ = to_state[i];
        }
        }
-
-      k = default_goto(i);
-      fprintf(ftable, "%6d", k);
-      save_column(i, k);
     }
 
     }
 
-  fprintf(ftable, "\n};\n");
-  FREE(state_count);
+  tally[symno] = count;
+  width[symno] = sp1[-1] - sp[0] + 1;
 }
 
 }
 
-
-
-int
+static int
 default_goto (int symbol)
 {
 default_goto (int symbol)
 {
-  register int i;
-  register int m;
-  register int n;
-  register int default_state;
-  register int max;
+  int i;
+  int m;
+  int n;
+  int default_state;
+  int max;
 
   m = goto_map[symbol];
   n = goto_map[symbol + 1];
 
   if (m == n)
 
   m = goto_map[symbol];
   n = goto_map[symbol + 1];
 
   if (m == n)
-    return (-1);
+    return -1;
 
   for (i = 0; i < nstates; i++)
     state_count[i] = 0;
 
   for (i = 0; i < nstates; i++)
     state_count[i] = 0;
@@ -990,68 +615,55 @@ default_goto (int symbol)
        }
     }
 
        }
     }
 
-  return (default_state);
+  return default_state;
 }
 
 
 }
 
 
-void
-save_column (int symbol, int default_state)
-{
-  register int i;
-  register int m;
-  register int n;
-  register short *sp;
-  register short *sp1;
-  register short *sp2;
-  register int count;
-  register int symno;
+/*-------------------------------------------------------------------.
+| Figure out what to do after reducing with each rule, depending on  |
+| the saved state from before the beginning of parsing the data that |
+| matched this rule.                                                 |
+|                                                                    |
+| The YYDEFGOTO table is output now.  The detailed info is saved for |
+| putting into YYTABLE later.                                        |
+`-------------------------------------------------------------------*/
 
 
-  m = goto_map[symbol];
-  n = goto_map[symbol + 1];
+static void
+goto_actions (void)
+{
+  int i;
+  short *yydefgoto = XMALLOC (short, nsyms - ntokens);
 
 
-  count = 0;
-  for (i = m; i < n; i++)
+  state_count = XCALLOC (short, nstates);
+  for (i = ntokens; i < nsyms; ++i)
     {
     {
-      if (to_state[i] != default_state)
-       count++;
+      int default_state = default_goto (i);
+      save_column (i, default_state);
+      yydefgoto[i - ntokens] = default_state;
     }
 
     }
 
-  if (count == 0)
-    return;
-
-  symno = symbol - ntokens + nstates;
-
-  froms[symno] = sp1 = sp = NEW2(count, short);
-  tos[symno] = sp2 = NEW2(count, short);
-
-  for (i = m; i < n; i++)
-    {
-      if (to_state[i] != default_state)
-       {
-         *sp1++ = from_state[i];
-         *sp2++ = to_state[i];
-       }
-    }
+  output_table_data (&output_obstack, yydefgoto,
+                    yydefgoto[0], 1, nsyms - ntokens);
+  muscle_insert ("defgoto", obstack_finish (&output_obstack));
 
 
-  tally[symno] = count;
-  width[symno] = sp1[-1] - sp[0] + 1;
+  XFREE (state_count);
+  XFREE (yydefgoto);
 }
 
 
 }
 
 
-
 /* The next few functions decide how to pack the actions and gotos
    information into yytable. */
 
 /* The next few functions decide how to pack the actions and gotos
    information into yytable. */
 
-void
+static void
 sort_actions (void)
 {
 sort_actions (void)
 {
-  register int i;
-  register int j;
-  register int k;
-  register int t;
-  register int w;
+  int i;
+  int j;
+  int k;
+  int t;
+  int w;
 
 
-  order = NEW2(nvectors, short);
+  order = XCALLOC (short, nvectors);
   nentries = 0;
 
   for (i = 0; i < nvectors; i++)
   nentries = 0;
 
   for (i = 0; i < nvectors; i++)
@@ -1078,69 +690,20 @@ sort_actions (void)
 }
 
 
 }
 
 
-void
-pack_table (void)
-{
-  register int i;
-  register int place;
-  register int state;
-
-  base = NEW2(nvectors, short);
-  pos = NEW2(nentries, short);
-  table = NEW2(MAXTABLE, short);
-  check = NEW2(MAXTABLE, short);
-
-  lowzero = 0;
-  high = 0;
-
-  for (i = 0; i < nvectors; i++)
-    base[i] = MINSHORT;
-
-  for (i = 0; i < MAXTABLE; i++)
-    check[i] = -1;
-
-  for (i = 0; i < nentries; i++)
-    {
-      state = matching_state(i);
-
-      if (state < 0)
-       place = pack_vector(i);
-      else
-       place = base[state];
-
-      pos[i] = place;
-      base[order[i]] = place;
-    }
-
-  for (i = 0; i < nvectors; i++)
-    {
-      if (froms[i])
-       FREE(froms[i]);
-      if (tos[i])
-       FREE(tos[i]);
-    }
-
-  FREE(froms);
-  FREE(tos);
-  FREE(pos);
-}
-
-
-
-int
+static int
 matching_state (int vector)
 {
 matching_state (int vector)
 {
-  register int i;
-  register int j;
-  register int k;
-  register int t;
-  register int w;
-  register int match;
-  register int prev;
+  int i;
+  int j;
+  int k;
+  int t;
+  int w;
+  int match;
+  int prev;
 
   i = order[vector];
   if (i >= nstates)
 
   i = order[vector];
   if (i >= nstates)
-    return (-1);
+    return -1;
 
   t = tally[i];
   w = width[i];
 
   t = tally[i];
   w = width[i];
@@ -1149,7 +712,7 @@ matching_state (int vector)
     {
       j = order[prev];
       if (width[j] != w || tally[j] != t)
     {
       j = order[prev];
       if (width[j] != w || tally[j] != t)
-       return (-1);
+       return -1;
 
       match = 1;
       for (k = 0; match && k < t; k++)
 
       match = 1;
       for (k = 0; match && k < t; k++)
@@ -1159,31 +722,29 @@ matching_state (int vector)
        }
 
       if (match)
        }
 
       if (match)
-       return (j);
+       return j;
     }
 
     }
 
-  return (-1);
+  return -1;
 }
 
 
 }
 
 
-
-int
+static int
 pack_vector (int vector)
 {
 pack_vector (int vector)
 {
-  register int i;
-  register int j;
-  register int k;
-  register int t;
-  register int loc = 0;
-  register int ok;
-  register short *from;
-  register short *to;
+  int i;
+  int j;
+  int k;
+  int t;
+  int loc = 0;
+  int ok;
+  short *from;
+  short *to;
 
   i = order[vector];
   t = tally[i];
 
 
   i = order[vector];
   t = tally[i];
 
-  if (t == 0)
-    berror("pack_vector");
+  assert (t);
 
   from = froms[i];
   to = tos[i];
 
   from = froms[i];
   to = tos[i];
@@ -1223,268 +784,296 @@ pack_vector (int vector)
          if (loc > high)
            high = loc;
 
          if (loc > high)
            high = loc;
 
-         return (j);
+         return j;
        }
     }
 
        }
     }
 
-  berror("pack_vector");
-  return 0;    /* JF keep lint happy */
+  assert (!"pack_vector");
+  return 0;
 }
 
 
 }
 
 
+static void
+pack_table (void)
+{
+  int i;
+  int place;
+  int state;
 
 
-/* the following functions output yytable, yycheck
-   and the vectors whose elements index the portion starts */
+  base = XCALLOC (short, nvectors);
+  pos = XCALLOC (short, nentries);
+  table = XCALLOC (short, MAXTABLE);
+  check = XCALLOC (short, MAXTABLE);
 
 
-void
-output_base (void)
-{
-  register int i;
-  register int j;
+  lowzero = 0;
+  high = 0;
 
 
-  fprintf(ftable, "\nstatic const short yypact[] = {%6d", base[0]);
+  for (i = 0; i < nvectors; i++)
+    base[i] = MINSHORT;
+
+  for (i = 0; i < MAXTABLE; i++)
+    check[i] = -1;
 
 
-  j = 10;
-  for (i = 1; i < nstates; i++)
+  for (i = 0; i < nentries; i++)
     {
     {
-      putc(',', ftable);
+      state = matching_state (i);
 
 
-      if (j >= 10)
-       {
-         putc('\n', ftable);
-         j = 1;
-       }
+      if (state < 0)
+       place = pack_vector (i);
       else
       else
-       {
-         j++;
-       }
+       place = base[state];
 
 
-      fprintf(ftable, "%6d", base[i]);
+      pos[i] = place;
+      base[order[i]] = place;
     }
 
     }
 
-  fprintf(ftable, "\n};\n\nstatic const short yypgoto[] = {%6d", base[nstates]);
-
-  j = 10;
-  for (i = nstates + 1; i < nvectors; i++)
+  for (i = 0; i < nvectors; i++)
     {
     {
-      putc(',', ftable);
-
-      if (j >= 10)
-       {
-         putc('\n', ftable);
-         j = 1;
-       }
-      else
-       {
-         j++;
-       }
-
-      fprintf(ftable, "%6d", base[i]);
+      if (froms[i])
+       XFREE (froms[i]);
+      if (tos[i])
+       XFREE (tos[i]);
     }
 
     }
 
-  fprintf(ftable, "\n};\n");
-  FREE(base);
+  XFREE (froms);
+  XFREE (tos);
+  XFREE (pos);
 }
 
 }
 
+/* the following functions output yytable, yycheck
+   and the vectors whose elements index the portion starts */
 
 
-void
-output_table (void)
+static void
+output_base (void)
 {
 {
-  register int i;
-  register int j;
-
-  fprintf(ftable, "\n\n#define\tYYLAST\t\t%d\n\n", high);
-  fprintf(ftable, "\nstatic const short yytable[] = {%6d", table[0]);
+  /* Output pact. */
+  output_table_data (&output_obstack, base,
+                    base[0], 1, nstates);
+  muscle_insert ("pact", obstack_finish (&output_obstack));
 
 
-  j = 10;
-  for (i = 1; i <= high; i++)
-    {
-      putc(',', ftable);
+  /* Output pgoto. */
+  output_table_data (&output_obstack, base,
+                    base[nstates], nstates + 1, nvectors);
+  muscle_insert ("pgoto", obstack_finish (&output_obstack));
 
 
-      if (j >= 10)
-       {
-         putc('\n', ftable);
-         j = 1;
-       }
-      else
-       {
-         j++;
-       }
+  XFREE (base);
+}
 
 
-      fprintf(ftable, "%6d", table[i]);
-    }
 
 
-  fprintf(ftable, "\n};\n");
-  FREE(table);
+static void
+output_table (void)
+{
+  output_table_data (&output_obstack, table,
+                    table[0], 1, high + 1);
+  muscle_insert ("table", obstack_finish (&output_obstack));
+  XFREE (table);
 }
 
 
 }
 
 
-void
+static void
 output_check (void)
 {
 output_check (void)
 {
-  register int i;
-  register int j;
-
-  fprintf(ftable, "\nstatic const short yycheck[] = {%6d", check[0]);
+  output_table_data (&output_obstack, check,
+                    check[0], 1, high + 1);
+  muscle_insert ("check", obstack_finish (&output_obstack));
+  XFREE (check);
+}
 
 
-  j = 10;
-  for (i = 1; i <= high; i++)
-    {
-      putc(',', ftable);
+/* compute and output yydefact, yydefgoto, yypact, yypgoto, yytable
+   and yycheck.  */
 
 
-      if (j >= 10)
-       {
-         putc('\n', ftable);
-         j = 1;
-       }
-      else
-       {
-         j++;
-       }
+static void
+output_actions (void)
+{
+  nvectors = nstates + nvars;
 
 
-      fprintf(ftable, "%6d", check[i]);
-    }
+  froms = XCALLOC (short *, nvectors);
+  tos = XCALLOC (short *, nvectors);
+  tally = XCALLOC (short, nvectors);
+  width = XCALLOC (short, nvectors);
 
 
-  fprintf(ftable, "\n};\n");
-  FREE(check);
-}
+  token_actions ();
+  LIST_FREE (shifts, first_shift);
+  LIST_FREE (reductions, first_reduction);
+  XFREE (LA);
+  XFREE (LAruleno);
 
 
+  goto_actions ();
+  XFREE (goto_map + ntokens);
+  XFREE (from_state);
+  XFREE (to_state);
 
 
+  sort_actions ();
+  pack_table ();
 
 
-/* copy the parser code into the ftable file at the end.  */
+  output_base ();
+  output_table ();
 
 
-void
-output_parser (void)
-{
-  register int c;
-#ifdef DONTDEF
-  FILE *fpars;
-#else
-#define fpars fparser
-#endif
+  output_check ();
+  LIST_FREE (state_t, first_state);
+  XFREE (state_table);
+}
 
 
-  if (pure_parser)
-    fprintf(ftable, "#define YYPURE 1\n\n");
+\f
+/*------------------------------------------------------------.
+| Copy the parser code from SKEL_FILENAME into OOUT obstack.  |
+| and do the muscle substitution.                             |
+`------------------------------------------------------------*/
 
 
-#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
+static void
+output_parser (const char *skel_filename, struct obstack *oout)
+{
+  int c;
+  FILE *fskel;
+  size_t line;
 
 
-  /* Loop over lines in the standard parser file.  */
+  fskel = xfopen (skel_filename, "r");
 
 
-  while (1)
+  /* New output code.  */
+  line = 1;
+  c = getc (fskel);
+  while (c != EOF)
     {
     {
-      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 == '$')
+      if (c != '%')
+       {
+         if (c == '\n')
+           ++line;
+         obstack_1grow (oout, c);
+         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 (muscle_value)
+           obstack_sgrow (oout, muscle_value);
+         else if (!strcmp (muscle_key, "line"))
+           obstack_fgrow1 (oout, "%d", line + 1);
+         else if (!strcmp (muscle_key, "input-line"))
+           obstack_fgrow1 (oout, "%d", lineno);
+         else
            {
            {
-             /* `$' 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);
+             obstack_sgrow (oout, "%%");
+             obstack_sgrow (oout, muscle_key);
            }
            }
-         else
-           putc(c, ftable);
        }
        }
-      if (c == EOF)
-       break;
-      putc(c, ftable);
+      else
+       obstack_1grow (oout, '%');
     }
     }
-}
 
 
-void
-output_program (void)
-{
-  register int c;
+  /* End.  */
+  xfclose (fskel);
+}
 
 
-  if (!nolinesflag)
-    fprintf(ftable, "#line %d \"%s\"\n", lineno, infile);
+/*----------------------------------------.
+| Prepare the master parser to be output  |
+`----------------------------------------*/
 
 
-  c = getc(finput);
-  while (c != EOF)
+static void
+output_master_parser (void)
+{
+  if (!skeleton)
     {
     {
-      putc(c, ftable);
-      c = getc(finput);
+      if (semantic_parser)
+       skeleton = skeleton_find ("BISON_HAIRY", BISON_HAIRY);
+      else
+       skeleton = skeleton_find ("BISON_SIMPLE", BISON_SIMPLE);
     }
     }
+  muscle_insert ("skeleton", skeleton);
+  output_parser (skeleton, &table_obstack);
 }
 
 
 }
 
 
-void
-free_itemsets (void)
-{
-  register core *cp,*cptmp;
+/* FIXME. */
 
 
-  FREE(state_table);
+#define MUSCLE_INSERT_INT(Key, Value)                          \
+{                                                              \
+  obstack_fgrow1 (&muscle_obstack, "%d", Value);               \
+  obstack_1grow (&muscle_obstack, 0);                          \
+  muscle_insert (Key, obstack_finish (&muscle_obstack));       \
+}
 
 
-  for (cp = first_state; cp; cp = cptmp) {
-    cptmp=cp->next;
-    FREE(cp);
-  }
+#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));               \
+}
 
 
-void
-free_shifts (void)
+static void
+prepare (void)
 {
 {
-  register shifts *sp,*sptmp;/* JF derefrenced freed ptr */
-
-  FREE(shift_table);
+  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_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);
+
+  /* We need to save the actions in the muscle %%action.  */
+  obstack_1grow (&action_obstack, 0);
+  muscle_insert ("action", obstack_finish (&action_obstack));
 
 
-  for (sp = first_shift; sp; sp = sptmp) {
-    sptmp=sp->next;
-    FREE(sp);
-  }
+  if (spec_name_prefix)
+    MUSCLE_INSERT_STRING ("prefix", spec_name_prefix);
 }
 
 }
 
+/*----------------------------------------------------------.
+| Output the parsing tables and the parser code to ftable.  |
+`----------------------------------------------------------*/
 
 void
 
 void
-free_reductions (void)
+output (void)
 {
 {
-  register reductions *rp,*rptmp;/* JF fixed freed ptr */
+  obstack_init (&output_obstack);
 
 
-  FREE(reduction_table);
+  output_token_translations ();
+  output_gram ();
 
 
-  for (rp = first_reduction; rp; rp = rptmp) {
-    rptmp=rp->next;
-    FREE(rp);
-  }
+  XFREE (ritem);
+  if (semantic_parser)
+    output_stos ();
+  output_rule_data ();
+  XFREE (user_toknums);
+  output_actions ();
+
+#if 0
+  if (!no_parser_flag) */
+#endif
+  prepare ();
+  /* Copy definitions in directive.  */
+  obstack_1grow (&attrs_obstack, 0);
+  muscle_insert ("prologue", obstack_finish (&attrs_obstack));
+
+  output_master_parser ();
+
+  obstack_free (&muscle_obstack, 0);
+  obstack_free (&output_obstack, 0);
+  obstack_free (&action_obstack, 0);
 }
 }