]> 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 113393f610b71c5ef72af5da20125463111a64b8..841ebe4f3780ec728f52920f437e27ad88a93f45 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 "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)
+/* Returns the number of lines of S.  */
+static size_t
+get_lines_number (const char *s)
 {
 {
-  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)
+  size_t lines = 0;
+  
+  size_t i;
+  for (i = 0; s[i]; ++i)
     {
     {
-      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);
-    }
+      if (s[i] == '\n')
+       ++lines;
+    }   
+  
+  return lines;
 }
 
 
 }
 
 
-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]);
-    }
-
-  fprintf(ftable, "\n};\n");
-
-  fprintf(ftable, "\nstatic const short yyrhs[] = {%6d", ritem[0]);
-
-  j = 10;
-  for (sp = ritem + 1; *sp; sp++)
-    {
-      putc(',', ftable);
-
-      if (j >= 10)
-       {
-         putc('\n', ftable);
-         j = 1;
-       }
-      else
-       {
-         j++;
-       }
-
-      if (*sp > 0)
-       fprintf(ftable, "%6d", *sp);
-      else
-       fprintf(ftable, "     0");
-    }
-
-  fprintf(ftable, "\n};\n");
-
-  if (! semantic_parser  && ! noparserflag)
-    fprintf(ftable, "\n#endif\n");
+  {
+    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);
+  }
+
+  muscle_insert ("prhs", obstack_finish (&output_obstack));
+
+  {
+    size_t yyrhs_size = 1;
+    short *yyrhs, *sp;
+    int i;
+
+    for (sp = ritem + 1; *sp; sp++)
+      ++yyrhs_size;
+    yyrhs = XMALLOC (short, yyrhs_size);
+
+    for (sp = ritem + 1, i = 1; *sp; ++sp, ++i)
+      yyrhs[i] = *sp > 0 ? *sp : 0;
+
+    output_table_data (&output_obstack, yyrhs,
+                      ritem[0], 1, yyrhs_size);
+    muscle_insert ("rhs", obstack_finish (&output_obstack));
+
+    XFREE (yyrhs);
+  }
+  
+#if 0
+  if (!semantic_parser)
+    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++)
+  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);
+  }
+
+
+  j = 0;
+  for (i = 0; i < nsyms; i++)
     {
     {
-      putc(',', ftable);
-
-      if (j >= 10)
+      /* 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.  */
+      int strsize = strlen (cp) + 2;
+
+      if (j + strsize > 75)
        {
        {
-         putc('\n', ftable);
-         j = 1;
-       }
-      else
-       {
-         j++;
+         obstack_sgrow (&output_obstack, "\n  ");
+         j = 2;
        }
 
        }
 
-      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.  */
-
-  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 */
-    {
-      register char *p;
-      putc(',', ftable);
-      j++;
-
-      if (j > 75)
-       {
-         putc('\n', ftable);
-         j = 0;
-       }
-
-      putc ('\"', ftable);
-      j++;
-
-      for (p = tags[i]; p && *p; p++)
-       {
-         if (*p == '"' || *p == '\\')
-           {
-             fprintf(ftable, "\\%c", *p);
-             j += 2;
-           }
-         else if (*p == '\n')
-           {
-             fprintf(ftable, "\\n");
-             j += 2;
-           }
-         else if (*p == '\t')
-           {
-             fprintf(ftable, "\\t");
-             j += 2;
-           }
-         else if (*p == '\b')
-           {
-             fprintf(ftable, "\\b");
-             j += 2;
-           }
-         else if (*p < 040 || *p >= 0177)
-           {
-             fprintf(ftable, "\\%03o", *p);
-             j += 4;
-           }
-         else
-           {
-             putc(*p, ftable);
-             j++;
-           }
-       }
-
-      putc ('\"', ftable);
-      j++;
+      obstack_sgrow (&output_obstack, cp);
+      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);
+    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);
 }
 
 }
 
-
-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();
-}
-
-
-
-/* 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)
     {
@@ -750,68 +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;
+      shift_state = shiftp->shifts[i];
+      if (!shift_state)
+       continue;
 
 
-      for (i = 0; i < k; i++)
-       {
-         shift_state = shiftp->shifts[i];
-         if (! shift_state) continue;
-
-         symbol = accessing_symbol[shift_state];
+      symbol = state_table[shift_state]->accessing_symbol;
 
 
-         if (ISVAR(symbol))
-           break;
+      if (ISVAR (symbol))
+       break;
 
 
-         actrow[symbol] = shift_state;
+      actrow[symbol] = shift_state;
 
 
-         /* Do not use any default reduction if there is a shift for
-            error */
-         if (symbol == error_token_number)
-           nodefault = 1;
-       }
+      /* Do not use any default reduction if there is a shift for
+        error */
+      if (symbol == error_token_number)
+       nodefault = 1;
     }
 
     }
 
-  errp = err_table[state];
-
   /* See which tokens are an explicit error in this state (due to
      %nonassoc).  For them, record MINSHORT as the action.  */
   /* See which tokens are an explicit error in this state (due to
      %nonassoc).  For them, record MINSHORT as the action.  */
+  errp = state_table[state]->errs;
 
   if (errp)
     {
 
   if (errp)
     {
@@ -827,17 +410,17 @@ 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++)
                {
@@ -863,7 +446,7 @@ action_row (int state)
                    actrow[j] = 0;
                }
 
                    actrow[j] = 0;
                }
 
-             default_rule = - default_rule;
+             default_rule = -default_rule;
            }
        }
     }
            }
        }
     }
@@ -882,14 +465,14 @@ action_row (int state)
 }
 
 
 }
 
 
-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++)
@@ -901,8 +484,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++)
     {
@@ -918,61 +501,121 @@ 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.                                       |
+`------------------------------------------------------------------*/
 
 
-/* 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.
+static void
+token_actions (void)
+{
+  int i;
+  short *yydefact = XCALLOC (short, nstates);
 
 
-   The yydefgoto table is output now.  The detailed info
-   is saved for putting into yytable later.  */
+  actrow = XCALLOC (short, ntokens);
+  for (i = 0; i < nstates; ++i)
+    {
+      yydefact[i] = action_row (i);
+      save_row (i);
+    }
 
 
-void
-goto_actions (void)
+  output_table_data (&output_obstack, yydefact,
+                    yydefact[0], 1, nstates);
+  muscle_insert ("defact", obstack_finish (&output_obstack));
+
+  XFREE (actrow);
+  XFREE (yydefact);
+}
+
+
+/*-----------------------------.
+| Output the actions to OOUT.  |
+`-----------------------------*/
+
+static void
+actions_output (FILE *out, size_t *line)
 {
 {
-  register int i;
-  register int j;
-  register int k;
+  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);
+      }
+}
+
 
 
-  state_count = NEW2(nstates, short);
+static void
+save_column (int symbol, int default_state)
+{
+  int i;
+  short *sp;
+  short *sp1;
+  short *sp2;
+  int count;
+  int symno;
 
 
-  k = default_goto(ntokens);
-  fprintf(ftable, "\nstatic const short yydefgoto[] = {%6d", k);
-  save_column(ntokens, k);
+  short begin = goto_map[symbol];
+  short end = goto_map[symbol + 1];
 
 
-  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];
 
   m = goto_map[symbol];
   n = goto_map[symbol + 1];
@@ -1002,64 +645,51 @@ default_goto (int symbol)
 }
 
 
 }
 
 
-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++)
@@ -1086,65 +716,16 @@ 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)
@@ -1174,24 +755,22 @@ matching_state (int vector)
 }
 
 
 }
 
 
-
-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];
@@ -1235,267 +814,343 @@ pack_vector (int vector)
        }
     }
 
        }
     }
 
-  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;
+
+  base = XCALLOC (short, nvectors);
+  pos = XCALLOC (short, nentries);
+  table = XCALLOC (short, MAXTABLE);
+  check = XCALLOC (short, MAXTABLE);
 
 
-/* the following functions output yytable, yycheck
-   and the vectors whose elements index the portion starts */
+  lowzero = 0;
+  high = 0;
 
 
-void
-output_base (void)
-{
-  register int i;
-  register int j;
+  for (i = 0; i < nvectors; i++)
+    base[i] = MINSHORT;
 
 
-  fprintf(ftable, "\nstatic const short yypact[] = {%6d", base[0]);
+  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;
+  output_table_data (&output_obstack, check,
+                    check[0], 1, high + 1);
+  muscle_insert ("check", obstack_finish (&output_obstack));
+  XFREE (check);
+}
 
 
-  fprintf(ftable, "\nstatic const short yycheck[] = {%6d", check[0]);
+/* compute and output yydefact, yydefgoto, yypact, yypgoto, yytable
+   and yycheck.  */
 
 
-  j = 10;
-  for (i = 1; i <= high; i++)
-    {
-      putc(',', ftable);
+static void
+output_actions (void)
+{
+  int i;
+  nvectors = nstates + nvars;
 
 
-      if (j >= 10)
-       {
-         putc('\n', ftable);
-         j = 1;
-       }
-      else
-       {
-         j++;
-       }
+  froms = XCALLOC (short *, nvectors);
+  tos = XCALLOC (short *, nvectors);
+  tally = XCALLOC (short, nvectors);
+  width = XCALLOC (short, nvectors);
 
 
-      fprintf(ftable, "%6d", check[i]);
-    }
+  token_actions ();
+  XFREE (LA);
+  XFREE (LAruleno);
 
 
-  fprintf(ftable, "\n};\n");
-  FREE(check);
-}
+  goto_actions ();
+  XFREE (goto_map + ntokens);
+  XFREE (from_state);
+  XFREE (to_state);
 
 
+  sort_actions ();
+  pack_table ();
 
 
+  output_base ();
+  output_table ();
 
 
-/* copy the parser code into the ftable file at the end.  */
+  output_check ();
 
 
-void
-output_parser (void)
-{
-  register int c;
-#ifdef DONTDEF
-  FILE *fpars;
-#else
-#define fpars fparser
-#endif
+  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);
+}
 
 
-  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, FILE *out)
+{
+  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;
+         putc (c, out);
+         c = getc (fskel);
+       }
+      else if ((c = getc (fskel)) == '%')
+       {
+         /* Read the muscle.  */
+         const char *muscle_key = 0;
+         const char *muscle_value = 0;
+
+         while (isalnum (c = getc (fskel)) || c == '-')
+           obstack_1grow (&muscle_obstack, c);
+         obstack_1grow (&muscle_obstack, 0);
+
+         /* Output the right value, or see if it's something special.  */
+         muscle_key = obstack_finish (&muscle_obstack);
+         muscle_value = muscle_find (muscle_key);
+         if (!strcmp (muscle_key, "actions"))
+           actions_output (out, &line);
+         else if (!strcmp (muscle_key, "line"))
+           fprintf (out, "%d", line);
+         else if (muscle_value)
            {
            {
-             /* `$' 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);
-           }
+             fputs (muscle_value, out);
+             line += get_lines_number (muscle_value);
+           }     
          else
          else
-           putc(c, ftable);
+           {
+             fputs ("%%", out);
+             fputs (muscle_key, out);
+           }
        }
        }
-      if (c == EOF)
-       break;
-      putc(c, ftable);
+      else
+       putc ('%', out);
     }
     }
-}
 
 
-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)
+{
+  FILE *parser = xfopen (parser_file_name, "w");
+  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);
+  muscle_insert ("parser-file-name", parser_file_name);
+
+  output_parser (skeleton, parser);
+  xfclose (parser);
 }
 
 
 }
 
 
-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 */
+  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);
+}
 
 
-  FREE(shift_table);
 
 
-  for (sp = first_shift; sp; sp = sptmp)
+/*-------------------------.
+| 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)
     {
     {
-      sptmp=sp->next;
-      FREE(sp);
+      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);
 }
 
 
 }
 
 
+/*----------------------------------------------------------.
+| 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 ();
+
+  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);
 }
 }