]> git.saurik.com Git - bison.git/blobdiff - src/reader.c
README-alpha: New.
[bison.git] / src / reader.c
index e35e4f38a7e890fab831c0febe1ffd7c583f1903..4f62e759a8e731c6af7f26311881c3c6988e6d58 100644 (file)
@@ -1,5 +1,5 @@
 /* Input parser for bison
 /* Input parser for bison
-   Copyright (C) 1984, 1986, 1989, 1992, 1998, 2000
+   Copyright 1984, 1986, 1989, 1992, 1998, 2000
    Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
    Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
@@ -21,6 +21,9 @@
 
 
 #include "system.h"
 
 
 #include "system.h"
+#include "obstack.h"
+#include "quotearg.h"
+#include "quote.h"
 #include "getargs.h"
 #include "files.h"
 #include "xalloc.h"
 #include "getargs.h"
 #include "files.h"
 #include "xalloc.h"
@@ -31,7 +34,6 @@
 #include "output.h"
 #include "reader.h"
 #include "conflicts.h"
 #include "output.h"
 #include "reader.h"
 #include "conflicts.h"
-#include "quote.h"
 
 /* Number of slots allocated (but not necessarily used yet) in `rline'  */
 static int rline_allocated;
 
 /* Number of slots allocated (but not necessarily used yet) in `rline'  */
 static int rline_allocated;
@@ -151,17 +153,18 @@ get_type_name (int n, symbol_list * rule)
   return rp->sym->type_name;
 }
 \f
   return rp->sym->type_name;
 }
 \f
-/*-------------------------------------------------------------------.
-| Dump the string from FINPUT to FOUTPUT.  MATCH is the delimiter of |
-| the string (either ' or ").                                        |
-`-------------------------------------------------------------------*/
+/*------------------------------------------------------------.
+| Dump the string from FIN to OOUT if non null.  MATCH is the |
+| delimiter of the string (either ' or ").                    |
+`------------------------------------------------------------*/
 
 static inline void
 
 static inline void
-copy_string (FILE *fin, FILE *fout, int match)
+copy_string (FILE *fin, struct obstack *oout, int match)
 {
   int c;
 
 {
   int c;
 
-  putc (match, fout);
+  obstack_1grow (oout, match);
+
   c = getc (fin);
 
   while (c != match)
   c = getc (fin);
 
   while (c != match)
@@ -176,14 +179,15 @@ copy_string (FILE *fin, FILE *fout, int match)
          continue;
        }
 
          continue;
        }
 
-      putc (c, fout);
+      obstack_1grow (oout, c);
 
       if (c == '\\')
        {
          c = getc (fin);
          if (c == EOF)
            fatal (_("unterminated string at end of file"));
 
       if (c == '\\')
        {
          c = getc (fin);
          if (c == EOF)
            fatal (_("unterminated string at end of file"));
-         putc (c, fout);
+         obstack_1grow (oout, c);
+
          if (c == '\n')
            lineno++;
        }
          if (c == '\n')
            lineno++;
        }
@@ -191,27 +195,47 @@ copy_string (FILE *fin, FILE *fout, int match)
       c = getc (fin);
     }
 
       c = getc (fin);
     }
 
-  putc (c, fout);
+  obstack_1grow (oout, c);
 }
 
 
 }
 
 
-/*---------------------------------------------------------------.
-| Dump the comment from IN to OUT1 and OUT2.  C is either `*' or |
-| `/', depending upon the type of comments used.  OUT2 might be  |
-| NULL.                                                          |
-`---------------------------------------------------------------*/
+/*-----------------------------------------------------------------.
+| Dump the wannabee comment from IN to OUT1 and OUT2 (which can be |
+| NULL).  In fact we just saw a `/', which might or might not be a |
+| comment.  In any case, copy what we saw.                         |
+|                                                                  |
+| OUT2 might be NULL.                                              |
+`-----------------------------------------------------------------*/
 
 static inline void
 
 static inline void
-copy_comment2 (FILE *in, FILE *out1, FILE *out2, int c)
+copy_comment2 (FILE *fin, struct obstack *oout1, struct obstack *oout2)
 {
   int cplus_comment;
   int ended;
 {
   int cplus_comment;
   int ended;
+  int c;
+
+  /* We read a `/', output it. */
+  obstack_1grow (oout1, '/');
+  if (oout2)
+    obstack_1grow (oout2, '/');
+
+  switch ((c = getc (fin)))
+    {
+    case '/':
+      cplus_comment = 1;
+      break;
+    case '*':
+      cplus_comment = 0;
+      break;
+    default:
+      ungetc (c, fin);
+      return;
+    }
 
 
-  cplus_comment = (c == '/');
-  putc (c, out1);
-  if (out2)
-    putc (c, out2);
-  c = getc (in);
+  obstack_1grow (oout1, c);
+  if (oout2)
+    obstack_1grow (oout2, c);
+  c = getc (fin);
 
   ended = 0;
   while (!ended)
 
   ended = 0;
   while (!ended)
@@ -220,82 +244,83 @@ copy_comment2 (FILE *in, FILE *out1, FILE *out2, int c)
        {
          while (c == '*')
            {
        {
          while (c == '*')
            {
-             putc (c, out1);
-             if (out2)
-               putc (c, out2);
-             c = getc (in);
+             obstack_1grow (oout1, c);
+             if (oout2)
+               obstack_1grow (oout2, c);
+             c = getc (fin);
            }
 
          if (c == '/')
            {
            }
 
          if (c == '/')
            {
-             putc (c, out1);
-             if (out2)
-               putc (c, out2);
+             obstack_1grow (oout1, c);
+             if (oout2)
+               obstack_1grow (oout2, c);
              ended = 1;
            }
        }
       else if (c == '\n')
        {
          lineno++;
              ended = 1;
            }
        }
       else if (c == '\n')
        {
          lineno++;
-         putc (c, out1);
-         if (out2)
-           putc (c, out2);
+         obstack_1grow (oout1, c);
+         if (oout2)
+           obstack_1grow (oout2, c);
          if (cplus_comment)
            ended = 1;
          else
          if (cplus_comment)
            ended = 1;
          else
-           c = getc (in);
+           c = getc (fin);
        }
       else if (c == EOF)
        fatal (_("unterminated comment"));
       else
        {
        }
       else if (c == EOF)
        fatal (_("unterminated comment"));
       else
        {
-         putc (c, out1);
-         if (out2)
-           putc (c, out2);
-         c = getc (in);
+         obstack_1grow (oout1, c);
+         if (oout2)
+           obstack_1grow (oout2, c);
+         c = getc (fin);
        }
     }
 }
 
 
        }
     }
 }
 
 
-/*------------------------------------------------------------.
-| Dump the comment from FIN to FOUT.  C is either `*' or `/', |
-| depending upon the type of comments used.                   |
-`------------------------------------------------------------*/
+/*-------------------------------------------------------------------.
+| Dump the comment (actually the current string starting with a `/') |
+| from FIN to OOUT.                                                  |
+`-------------------------------------------------------------------*/
 
 static inline void
 
 static inline void
-copy_comment (FILE *fin, FILE *fout, int c)
+copy_comment (FILE *fin, struct obstack *oout)
 {
 {
-  copy_comment2 (fin, fout, NULL, c);
+  copy_comment2 (fin, oout, NULL);
 }
 
 
 /*-----------------------------------------------------------------.
 }
 
 
 /*-----------------------------------------------------------------.
-| FIN is pointing to a location (i.e., a `@').  Output to FOUT a   |
+| FIN is pointing to a location (i.e., a `@').  Output to OOUT a   |
 | reference to this location. STACK_OFFSET is the number of values |
 | in the current rule so far, which says where to find `$0' with   |
 | respect to the top of the stack.                                 |
 `-----------------------------------------------------------------*/
 
 static inline void
 | reference to this location. STACK_OFFSET is the number of values |
 | in the current rule so far, which says where to find `$0' with   |
 | respect to the top of the stack.                                 |
 `-----------------------------------------------------------------*/
 
 static inline void
-copy_at (FILE *fin, FILE *fout, int stack_offset)
+copy_at (FILE *fin, struct obstack *oout, int stack_offset)
 {
   int c;
 
   c = getc (fin);
   if (c == '$')
     {
 {
   int c;
 
   c = getc (fin);
   if (c == '$')
     {
-      fprintf (fout, "yyloc");
+      obstack_sgrow (oout, "yyloc");
       locations_flag = 1;
     }
   else if (isdigit (c) || c == '-')
     {
       int n;
       locations_flag = 1;
     }
   else if (isdigit (c) || c == '-')
     {
       int n;
+      char buf[4096];
 
       ungetc (c, fin);
       n = read_signed_integer (fin);
 
 
       ungetc (c, fin);
       n = read_signed_integer (fin);
 
-      fprintf (fout, "yylsp[%d]", n - stack_offset);
+      obstack_fgrow1 (oout, "yylsp[%d]", n - stack_offset);
       locations_flag = 1;
     }
   else
       locations_flag = 1;
     }
   else
@@ -312,44 +337,35 @@ copy_at (FILE *fin, FILE *fout, int stack_offset)
 |                                                                    |
 | Possible inputs: $[<TYPENAME>]($|integer)                          |
 |                                                                    |
 |                                                                    |
 | Possible inputs: $[<TYPENAME>]($|integer)                          |
 |                                                                    |
-| Output to FOUT a reference to this semantic value. STACK_OFFSET is |
+| Output to OOUT a reference to this semantic value. STACK_OFFSET is |
 | the number of values in the current rule so far, which says where  |
 | to find `$0' with respect to the top of the stack.                 |
 `-------------------------------------------------------------------*/
 
 static inline void
 | the number of values in the current rule so far, which says where  |
 | to find `$0' with respect to the top of the stack.                 |
 `-------------------------------------------------------------------*/
 
 static inline void
-copy_dollar (FILE *fin, FILE *fout,
+copy_dollar (FILE *fin, struct obstack *oout,
             symbol_list *rule, int stack_offset)
 {
   int c = getc (fin);
   char *type_name = NULL;
 
             symbol_list *rule, int stack_offset)
 {
   int c = getc (fin);
   char *type_name = NULL;
 
-  /* Get the typename if explicit. */
+  /* Get the type name if explicit. */
   if (c == '<')
     {
   if (c == '<')
     {
-      char *cp = token_buffer;
-
-      while ((c = getc (fin)) != '>' && c > 0)
-       {
-         if (cp == token_buffer + maxtoken)
-           cp = grow_token_buffer (cp);
-
-         *cp++ = c;
-       }
-      *cp = 0;
+      read_type_name (fin);
       type_name = token_buffer;
       value_components_used = 1;
       type_name = token_buffer;
       value_components_used = 1;
-
       c = getc (fin);
     }
 
   if (c == '$')
     {
       c = getc (fin);
     }
 
   if (c == '$')
     {
-      fprintf (fout, "yyval");
+      obstack_sgrow (oout, "yyval");
+
       if (!type_name)
        type_name = get_type_name (0, rule);
       if (type_name)
       if (!type_name)
        type_name = get_type_name (0, rule);
       if (type_name)
-       fprintf (fout, ".%s", type_name);
+       obstack_fgrow1 (oout, ".%s", type_name);
       if (!type_name && typed)
        complain (_("$$ of `%s' has no declared type"),
                  rule->sym->tag);
       if (!type_name && typed)
        complain (_("$$ of `%s' has no declared type"),
                  rule->sym->tag);
@@ -363,9 +379,10 @@ copy_dollar (FILE *fin, FILE *fout,
       if (!type_name && n > 0)
        type_name = get_type_name (n, rule);
 
       if (!type_name && n > 0)
        type_name = get_type_name (n, rule);
 
-      fprintf (fout, "yyvsp[%d]", n - stack_offset);
+      obstack_fgrow1 (oout, "yyvsp[%d]", n - stack_offset);
+
       if (type_name)
       if (type_name)
-       fprintf (fout, ".%s", type_name);
+       obstack_fgrow1 (oout, ".%s", type_name);
       if (!type_name && typed)
        complain (_("$%d of `%s' has no declared type"),
                  n, rule->sym->tag);
       if (!type_name && typed)
        complain (_("$%d of `%s' has no declared type"),
                  n, rule->sym->tag);
@@ -391,7 +408,8 @@ copy_definition (void)
   int after_percent;
 
   if (!no_lines_flag)
   int after_percent;
 
   if (!no_lines_flag)
-    fprintf (fattrs, "#line %d \"%s\"\n", lineno, infile);
+    obstack_fgrow2 (&attrs_obstack, "#line %d %s\n",
+                   lineno, quotearg_style (c_quoting_style, infile));
 
   after_percent = 0;
 
 
   after_percent = 0;
 
@@ -402,7 +420,7 @@ copy_definition (void)
       switch (c)
        {
        case '\n':
       switch (c)
        {
        case '\n':
-         putc (c, fattrs);
+         obstack_1grow (&attrs_obstack, c);
          lineno++;
          break;
 
          lineno++;
          break;
 
@@ -412,22 +430,18 @@ copy_definition (void)
 
        case '\'':
        case '"':
 
        case '\'':
        case '"':
-         copy_string (finput, fattrs, c);
+         copy_string (finput, &attrs_obstack, c);
          break;
 
        case '/':
          break;
 
        case '/':
-         putc (c, fattrs);
-         c = getc (finput);
-         if (c != '*' && c != '/')
-           continue;
-         copy_comment (finput, fattrs, c);
+         copy_comment (finput, &attrs_obstack);
          break;
 
        case EOF:
          fatal ("%s", _("unterminated `%{' definition"));
 
        default:
          break;
 
        case EOF:
          fatal ("%s", _("unterminated `%{' definition"));
 
        default:
-         putc (c, fattrs);
+         obstack_1grow (&attrs_obstack, c);
        }
 
       c = getc (finput);
        }
 
       c = getc (finput);
@@ -436,12 +450,10 @@ copy_definition (void)
        {
          if (c == '}')
            return;
        {
          if (c == '}')
            return;
-         putc ('%', fattrs);
+         obstack_1grow (&attrs_obstack, '%');
        }
       after_percent = 0;
        }
       after_percent = 0;
-
     }
     }
-
 }
 
 
 }
 
 
@@ -456,12 +468,18 @@ parse_token_decl (symbol_class what_is, symbol_class what_is_not)
 {
   int token = 0;
   char *typename = 0;
 {
   int token = 0;
   char *typename = 0;
-  struct bucket *symbol = NULL;        /* pts to symbol being defined */
 
 
+  /* The symbol being defined.  */
+  struct bucket *symbol = NULL;
+
+  /* After `%token' and `%nterm', any number of symbols maybe be
+     defined.  */
   for (;;)
     {
       int tmp_char = ungetc (skip_white_space (), finput);
 
   for (;;)
     {
       int tmp_char = ungetc (skip_white_space (), finput);
 
+      /* `%' (for instance from `%token', or from `%%' etc.) is the
+        only valid means to end this declaration.  */
       if (tmp_char == '%')
        return;
       if (tmp_char == EOF)
       if (tmp_char == '%')
        return;
       if (tmp_char == EOF)
@@ -691,11 +709,11 @@ token_buffer);
 
 
 
 
 
 
-/*-------------------------------------------------------------------.
-| Copy the union declaration into fattrs (and fdefines), where it is |
-| made into the definition of YYSTYPE, the type of elements of the   |
-| parser value stack.                                                |
-`-------------------------------------------------------------------*/
+/*--------------------------------------------------------------.
+| Copy the union declaration into ATTRS_OBSTACK (and fdefines), |
+| where it is made into the definition of YYSTYPE, the type of  |
+| elements of the parser value stack.                           |
+`--------------------------------------------------------------*/
 
 static void
 parse_union_decl (void)
 
 static void
 parse_union_decl (void)
@@ -709,21 +727,22 @@ parse_union_decl (void)
   typed = 1;
 
   if (!no_lines_flag)
   typed = 1;
 
   if (!no_lines_flag)
-    fprintf (fattrs, "\n#line %d \"%s\"\n", lineno, infile);
+    obstack_fgrow2 (&attrs_obstack, "\n#line %d %s\n",
+                   lineno, quotearg_style (c_quoting_style, infile));
   else
   else
-    fprintf (fattrs, "\n");
+    obstack_1grow (&attrs_obstack, '\n');
 
 
-  fprintf (fattrs, "typedef union");
-  if (fdefines)
-    fprintf (fdefines, "typedef union");
+  obstack_sgrow (&attrs_obstack, "typedef union");
+  if (defines_flag)
+    obstack_sgrow (&defines_obstack, "typedef union");
 
   c = getc (finput);
 
   while (c != EOF)
     {
 
   c = getc (finput);
 
   while (c != EOF)
     {
-      putc (c, fattrs);
-      if (fdefines)
-       putc (c, fdefines);
+      obstack_1grow (&attrs_obstack, c);
+      if (defines_flag)
+       obstack_1grow (&defines_obstack, c);
 
       switch (c)
        {
 
       switch (c)
        {
@@ -732,13 +751,9 @@ parse_union_decl (void)
          break;
 
        case '/':
          break;
 
        case '/':
-         c = getc (finput);
-         if (c != '*' && c != '/')
-           continue;
-         copy_comment2 (finput, fattrs, fdefines, c);
+         copy_comment2 (finput, &defines_obstack, &attrs_obstack);
          break;
 
          break;
 
-
        case '{':
          count++;
          break;
        case '{':
          count++;
          break;
@@ -749,9 +764,9 @@ parse_union_decl (void)
          count--;
          if (count <= 0)
            {
          count--;
          if (count <= 0)
            {
-             fprintf (fattrs, " YYSTYPE;\n");
-             if (fdefines)
-               fprintf (fdefines, " YYSTYPE;\n");
+             obstack_sgrow (&attrs_obstack, " YYSTYPE;\n");
+             if (defines_flag)
+               obstack_sgrow (&defines_obstack, " YYSTYPE;\n");
              /* JF don't choke on trailing semi */
              c = skip_white_space ();
              if (c != ';')
              /* JF don't choke on trailing semi */
              c = skip_white_space ();
              if (c != ';')
@@ -773,28 +788,13 @@ parse_union_decl (void)
 static void
 parse_expect_decl (void)
 {
 static void
 parse_expect_decl (void)
 {
-  int c;
-  size_t count;
-  char buffer[20];
-
-  c = getc (finput);
-  while (c == ' ' || c == '\t')
-    c = getc (finput);
-
-  count = 0;
-  while (c >= '0' && c <= '9')
-    {
-      if (count < sizeof(buffer) - 1)
-       buffer[count++] = c;
-      c = getc (finput);
-    }
-  buffer[count] = 0;
-
+  int c = skip_white_space ();
   ungetc (c, finput);
 
   ungetc (c, finput);
 
-  if (count <= 0 || count > 10)
+  if (!isdigit (c))
     complain (_("argument of %%expect is not an integer"));
     complain (_("argument of %%expect is not an integer"));
-  expected_conflicts = atoi (buffer);
+  else
+    expected_conflicts = read_signed_integer (finput);
 }
 
 
 }
 
 
@@ -882,7 +882,7 @@ parse_thong_decl (void)
 /*----------------------------------------------------------------.
 | Read from finput until `%%' is seen.  Discard the `%%'.  Handle |
 | any `%' declarations, and copy the contents of any `%{ ... %}'  |
 /*----------------------------------------------------------------.
 | Read from finput until `%%' is seen.  Discard the `%%'.  Handle |
 | any `%' declarations, and copy the contents of any `%{ ... %}'  |
-| groups to fattrs.                                               |
+| groups to ATTRS_OBSTACK.                                        |
 `----------------------------------------------------------------*/
 
 static void
 `----------------------------------------------------------------*/
 
 static void
@@ -948,11 +948,7 @@ read_declarations (void)
              break;
 
            case SEMANTIC_PARSER:
              break;
 
            case SEMANTIC_PARSER:
-             if (semantic_parser == 0)
-               {
-                 semantic_parser = 1;
-                 open_extra_files ();
-               }
+             semantic_parser = 1;
              break;
 
            case PURE_PARSER:
              break;
 
            case PURE_PARSER:
@@ -991,15 +987,22 @@ copy_action (symbol_list *rule, int stack_offset)
 {
   int c;
   int count;
 {
   int c;
   int count;
+  char buf[4096];
 
   /* offset is always 0 if parser has already popped the stack pointer */
   if (semantic_parser)
     stack_offset = 0;
 
 
   /* offset is always 0 if parser has already popped the stack pointer */
   if (semantic_parser)
     stack_offset = 0;
 
-  fprintf (faction, "\ncase %d:\n", nrules);
+  sprintf (buf, "\ncase %d:\n", nrules);
+  obstack_grow (&action_obstack, buf, strlen (buf));
+
   if (!no_lines_flag)
   if (!no_lines_flag)
-    fprintf (faction, "#line %d \"%s\"\n", lineno, infile);
-  putc ('{', faction);
+    {
+      sprintf (buf, "#line %d %s\n",
+              lineno, quotearg_style (c_quoting_style, infile));
+      obstack_grow (&action_obstack, buf, strlen (buf));
+    }
+  obstack_1grow (&action_obstack, '{');
 
   count = 1;
   c = getc (finput);
 
   count = 1;
   c = getc (finput);
@@ -1011,41 +1014,39 @@ copy_action (symbol_list *rule, int stack_offset)
          switch (c)
            {
            case '\n':
          switch (c)
            {
            case '\n':
-             putc (c, faction);
+             obstack_1grow (&action_obstack, c);
              lineno++;
              break;
 
            case '{':
              lineno++;
              break;
 
            case '{':
-             putc (c, faction);
+             obstack_1grow (&action_obstack, c);
              count++;
              break;
 
            case '\'':
            case '"':
              count++;
              break;
 
            case '\'':
            case '"':
-             copy_string (finput, faction, c);
+             copy_string (finput, &action_obstack, c);
              break;
 
            case '/':
              break;
 
            case '/':
-             putc (c, faction);
-             c = getc (finput);
-             if (c != '*' && c != '/')
-               continue;
-             copy_comment (finput, faction, c);
+             copy_comment (finput, &action_obstack);
              break;
 
            case '$':
              break;
 
            case '$':
-             copy_dollar (finput, faction, rule, stack_offset);
+             copy_dollar (finput, &action_obstack,
+                          rule, stack_offset);
              break;
 
            case '@':
              break;
 
            case '@':
-             copy_at (finput, faction, stack_offset);
+             copy_at (finput, &action_obstack,
+                      stack_offset);
              break;
 
            case EOF:
              fatal (_("unmatched %s"), "`{'");
 
            default:
              break;
 
            case EOF:
              fatal (_("unmatched %s"), "`{'");
 
            default:
-             putc (c, faction);
+             obstack_1grow (&action_obstack, c);
            }
 
          c = getc (finput);
            }
 
          c = getc (finput);
@@ -1055,12 +1056,12 @@ copy_action (symbol_list *rule, int stack_offset)
 
       if (--count)
        {
 
       if (--count)
        {
-         putc (c, faction);
+         obstack_1grow (&action_obstack, c);
          c = getc (finput);
        }
     }
 
          c = getc (finput);
        }
     }
 
-  fprintf (faction, ";\n    break;}");
+  obstack_sgrow (&action_obstack, ";\n    break;}");
 }
 \f
 /*-------------------------------------------------------------------.
 }
 \f
 /*-------------------------------------------------------------------.
@@ -1083,10 +1084,11 @@ copy_guard (symbol_list *rule, int stack_offset)
   if (semantic_parser)
     stack_offset = 0;
 
   if (semantic_parser)
     stack_offset = 0;
 
-  fprintf (fguard, "\ncase %d:\n", nrules);
+  obstack_fgrow1 (&guard_obstack, "\ncase %d:\n", nrules);
   if (!no_lines_flag)
   if (!no_lines_flag)
-    fprintf (fguard, "#line %d \"%s\"\n", lineno, infile);
-  putc ('{', fguard);
+    obstack_fgrow2 (&guard_obstack, "#line %d %s\n",
+                   lineno, quotearg_style (c_quoting_style, infile));
+  obstack_1grow (&guard_obstack, '{');
 
   count = 0;
   c = getc (finput);
 
   count = 0;
   c = getc (finput);
@@ -1096,18 +1098,18 @@ copy_guard (symbol_list *rule, int stack_offset)
       switch (c)
        {
        case '\n':
       switch (c)
        {
        case '\n':
-         putc (c, fguard);
+         obstack_1grow (&guard_obstack, c);
          lineno++;
          break;
 
        case '{':
          lineno++;
          break;
 
        case '{':
-         putc (c, fguard);
+         obstack_1grow (&guard_obstack, c);
          brace_flag = 1;
          count++;
          break;
 
        case '}':
          brace_flag = 1;
          count++;
          break;
 
        case '}':
-         putc (c, fguard);
+         obstack_1grow (&guard_obstack, c);
          if (count > 0)
            count--;
          else
          if (count > 0)
            count--;
          else
@@ -1119,30 +1121,26 @@ copy_guard (symbol_list *rule, int stack_offset)
 
        case '\'':
        case '"':
 
        case '\'':
        case '"':
-         copy_string (finput, fguard, c);
+         copy_string (finput, &guard_obstack, c);
          break;
 
        case '/':
          break;
 
        case '/':
-         putc (c, fguard);
-         c = getc (finput);
-         if (c != '*' && c != '/')
-           continue;
-         copy_comment (finput, fguard, c);
+         copy_comment (finput, &guard_obstack);
          break;
 
        case '$':
          break;
 
        case '$':
-         copy_dollar (finput, fguard, rule, stack_offset);
+         copy_dollar (finput, &guard_obstack, rule, stack_offset);
          break;
 
        case '@':
          break;
 
        case '@':
-         copy_at (finput, fguard, stack_offset);
+         copy_at (finput, &guard_obstack, stack_offset);
          break;
 
        case EOF:
          fatal ("%s", _("unterminated %guard clause"));
 
        default:
          break;
 
        case EOF:
          fatal ("%s", _("unterminated %guard clause"));
 
        default:
-         putc (c, fguard);
+         obstack_1grow (&guard_obstack, c);
        }
 
       if (c != '}' || count != 0)
        }
 
       if (c != '}' || count != 0)
@@ -1151,7 +1149,7 @@ copy_guard (symbol_list *rule, int stack_offset)
 
   c = skip_white_space ();
 
 
   c = skip_white_space ();
 
-  fprintf (fguard, ";\n    break;}");
+  obstack_sgrow (&guard_obstack, ";\n    break;}");
   if (c == '{')
     copy_action (rule, stack_offset);
   else if (c == '=')
   if (c == '{')
     copy_action (rule, stack_offset);
   else if (c == '=')
@@ -1383,9 +1381,9 @@ readgram (void)
                {
                  bucket *sdummy;
 
                {
                  bucket *sdummy;
 
-                 /* Since the action was written out with this rule's */
-                 /* number, we must give the new rule this number */
-                 /* by inserting the new rule before it.  */
+                 /* Since the action was written out with this rule's
+                    number, we must give the new rule this number by
+                    inserting the new rule before it.  */
 
                  /* Make a dummy nonterminal, a gensym.  */
                  sdummy = gensym ();
 
                  /* Make a dummy nonterminal, a gensym.  */
                  sdummy = gensym ();
@@ -1406,7 +1404,8 @@ readgram (void)
                  p->next = crule1;
                  crule1->next = crule;
 
                  p->next = crule1;
                  crule1->next = crule;
 
-                 /* insert the dummy generated by that rule into this rule.  */
+                 /* Insert the dummy generated by that rule into this
+                    rule.  */
                  nitems++;
                  p = XCALLOC (symbol_list, 1);
                  p->sym = sdummy;
                  nitems++;
                  p = XCALLOC (symbol_list, 1);
                  p->sym = sdummy;
@@ -1541,9 +1540,13 @@ readgram (void)
       /* We used to use `unsigned long' as YYSTYPE on MSDOS,
          but it seems better to be consistent.
          Most programs should declare their own type anyway.  */
       /* We used to use `unsigned long' as YYSTYPE on MSDOS,
          but it seems better to be consistent.
          Most programs should declare their own type anyway.  */
-      fprintf (fattrs, "#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n");
-      if (fdefines)
-       fprintf (fdefines, "#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n");
+      obstack_sgrow (&attrs_obstack,
+                          "#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n");
+      if (defines_flag)
+       obstack_sgrow (&defines_obstack, "\
+#ifndef YYSTYPE\n\
+# define YYSTYPE int\n\
+#endif\n");
     }
 
   /* Report any undefined symbols and consider them nonterminals.  */
     }
 
   /* Report any undefined symbols and consider them nonterminals.  */
@@ -1567,7 +1570,7 @@ readgram (void)
 `--------------------------------------------------------------*/
 
 static void
 `--------------------------------------------------------------*/
 
 static void
-output_token_defines (FILE *file)
+output_token_defines (struct obstack *oout)
 {
   bucket *bp;
   char *cp, *symbol;
 {
   bucket *bp;
   char *cp, *symbol;
@@ -1600,14 +1603,15 @@ output_token_defines (FILE *file)
       if (c != '\0')
        continue;
 
       if (c != '\0')
        continue;
 
-      fprintf (file, "#define\t%s\t%d\n", symbol,
-              ((translations && !raw_flag)
-               ? bp->user_token_number : bp->value));
+      obstack_fgrow2 (oout, "#define\t%s\t%d\n",
+                     symbol,
+                     ((translations && !raw_flag)
+                      ? bp->user_token_number : bp->value));
       if (semantic_parser)
       if (semantic_parser)
-       fprintf (file, "#define\tT%s\t%d\n", symbol, bp->value);
+       obstack_fgrow2 (oout, "#define\tT%s\t%d\n", symbol, bp->value);
     }
 
     }
 
-  putc ('\n', file);
+  obstack_1grow (oout, '\n');
 }
 
 
 }
 
 
@@ -1730,7 +1734,7 @@ packsymbols (void)
   error_token_number = errtoken->value;
 
   if (!no_parser_flag)
   error_token_number = errtoken->value;
 
   if (!no_parser_flag)
-    output_token_defines (ftable);
+    output_token_defines (&table_obstack);
 
   if (startval->class == unknown_sym)
     fatal (_("the start symbol %s is undefined"), startval->tag);
 
   if (startval->class == unknown_sym)
     fatal (_("the start symbol %s is undefined"), startval->tag);
@@ -1741,15 +1745,16 @@ packsymbols (void)
 
   if (defines_flag)
     {
 
   if (defines_flag)
     {
-      output_token_defines (fdefines);
+      output_token_defines (&defines_obstack);
 
       if (!pure_parser)
        {
          if (spec_name_prefix)
 
       if (!pure_parser)
        {
          if (spec_name_prefix)
-           fprintf (fdefines, "\nextern YYSTYPE %slval;\n",
-                    spec_name_prefix);
+           obstack_fgrow1 (&defines_obstack, "\nextern YYSTYPE %slval;\n",
+                           spec_name_prefix);
          else
          else
-           fprintf (fdefines, "\nextern YYSTYPE yylval;\n");
+           obstack_sgrow (&defines_obstack,
+                                "\nextern YYSTYPE yylval;\n");
        }
 
       if (semantic_parser)
        }
 
       if (semantic_parser)
@@ -1757,7 +1762,8 @@ packsymbols (void)
          {
            /* don't make these for dummy nonterminals made by gensym.  */
            if (*tags[i] != '@')
          {
            /* don't make these for dummy nonterminals made by gensym.  */
            if (*tags[i] != '@')
-             fprintf (fdefines, "#define\tNT%s\t%d\n", tags[i], i);
+              obstack_fgrow2 (&defines_obstack,
+                              "#define\tNT%s\t%d\n", tags[i], i);
          }
 #if 0
       /* `fdefines' is now a temporary file, so we need to copy its
          }
 #if 0
       /* `fdefines' is now a temporary file, so we need to copy its
@@ -1836,10 +1842,10 @@ packgram (void)
 \f
 /*-------------------------------------------------------------------.
 | Read in the grammar specification and record it in the format      |
 \f
 /*-------------------------------------------------------------------.
 | Read in the grammar specification and record it in the format      |
-| described in gram.h.  All guards are copied into the FGUARD file   |
-| and all actions into FACTION, in each case forming the body of a C |
-| function (YYGUARD or YYACTION) which contains a switch statement   |
-| to decide which guard or action to execute.                        |
+| described in gram.h.  All guards are copied into the GUARD_OBSTACK |
+| and all actions into ACTION_OBSTACK, in each case forming the body |
+| of a C function (YYGUARD or YYACTION) which contains a switch      |
+| statement to decide which guard or action to execute.              |
 `-------------------------------------------------------------------*/
 
 void
 `-------------------------------------------------------------------*/
 
 void
@@ -1889,16 +1895,19 @@ reader (void)
   undeftoken->class = token_sym;
   undeftoken->user_token_number = 2;
 
   undeftoken->class = token_sym;
   undeftoken->user_token_number = 2;
 
-  /* Read the declaration section.  Copy %{ ... %} groups to FTABLE
-     and FDEFINES file.  Also notice any %token, %left, etc. found
-     there.  */
-  putc ('\n', ftable);
-  fprintf (ftable, "\
+  /* Read the declaration section.  Copy %{ ... %} groups to
+     TABLE_OBSTACK and FDEFINES file.  Also notice any %token, %left,
+     etc. found there.  */
+  obstack_1grow (&table_obstack, '\n');
+  obstack_fgrow3 (&table_obstack, "\
 /* %s, made from %s\n\
    by GNU bison %s.  */\n\
 /* %s, made from %s\n\
    by GNU bison %s.  */\n\
-\n", no_parser_flag ? "Bison-generated parse tables" : "A Bison parser", infile, VERSION);
+\n",
+                 no_parser_flag ? "Bison-generated parse tables" : "A Bison parser",
+                 infile, VERSION);
 
 
-  fputs ("#define YYBISON 1  /* Identify Bison output.  */\n\n", ftable);
+  obstack_sgrow (&table_obstack,
+                      "#define YYBISON 1  /* Identify Bison output.  */\n\n");
   read_declarations ();
   /* Start writing the guard and action files, if they are needed.  */
   output_headers ();
   read_declarations ();
   /* Start writing the guard and action files, if they are needed.  */
   output_headers ();
@@ -1907,12 +1916,12 @@ reader (void)
   readgram ();
   /* Now we know whether we need the line-number stack.  If we do,
      write its type into the .tab.h file.  */
   readgram ();
   /* Now we know whether we need the line-number stack.  If we do,
      write its type into the .tab.h file.  */
-  if (fdefines)
-    reader_output_yylsp (fdefines);
+  if (defines_flag)
+    reader_output_yylsp (&defines_obstack);
   /* Write closing delimiters for actions and guards.  */
   output_trailers ();
   if (locations_flag)
   /* Write closing delimiters for actions and guards.  */
   output_trailers ();
   if (locations_flag)
-    fputs ("#define YYLSP_NEEDED\n\n", ftable);
+    obstack_sgrow (&table_obstack, "#define YYLSP_NEEDED 1\n\n");
   /* Assign the symbols their symbol numbers.  Write #defines for the
      token symbols into FDEFINES if requested.  */
   packsymbols ();
   /* Assign the symbols their symbol numbers.  Write #defines for the
      token symbols into FDEFINES if requested.  */
   packsymbols ();
@@ -1924,26 +1933,28 @@ reader (void)
 }
 
 
 }
 
 
+/*------------------------------------------------------------------.
+| Define YYLTYPE.  Cannot be in the skeleton since we might have to |
+| output it in the headers if --defines is used.                    |
+`------------------------------------------------------------------*/
+
 void
 void
-reader_output_yylsp (FILE *f)
+reader_output_yylsp (struct obstack *oout)
 {
   if (locations_flag)
 {
   if (locations_flag)
-    fputs ("\
+    obstack_sgrow (oout, "\
 \n\
 #ifndef YYLTYPE\n\
 typedef struct yyltype\n\
 {\n\
 \n\
 #ifndef YYLTYPE\n\
 typedef struct yyltype\n\
 {\n\
-  int timestamp;\n\
   int first_line;\n\
   int first_line;\n\
-  int first_column;\
+  int first_column;\n\
 \n\
   int last_line;\n\
   int last_column;\n\
 \n\
   int last_line;\n\
   int last_column;\n\
-  char *text;\n\
 } yyltype;\n\
 \n\
 # define YYLTYPE yyltype\n\
 #endif\n\
 } yyltype;\n\
 \n\
 # define YYLTYPE yyltype\n\
 #endif\n\
-\n",
-          f);
+\n");
 }
 }