]> git.saurik.com Git - bison.git/blobdiff - src/output.c
Fix push parsing memory leak reported by Brandon Lucia at
[bison.git] / src / output.c
index 51541822c44c7c4b7178554a416f9ec00f223122..ef7683ec09dd7fb33add5384ed40aa8ddaa94da8 100644 (file)
@@ -1,7 +1,7 @@
 /* Output the generated parsing program for Bison.
 
 /* Output the generated parsing program for Bison.
 
-   Copyright (C) 1984, 1986, 1989, 1992, 2000, 2001, 2002, 2003, 2004, 2005
-   Free Software Foundation, Inc.
+   Copyright (C) 1984, 1986, 1989, 1992, 2000, 2001, 2002, 2003, 2004,
+   2005, 2006, 2007 Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
 
    This file is part of Bison, the GNU Compiler Compiler.
 
    Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.  */
 
    Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.  */
 
-
+#include <config.h>
 #include "system.h"
 
 #include "system.h"
 
+#include <configmake.h>
 #include <error.h>
 #include <get-errno.h>
 #include <quotearg.h>
 #include <error.h>
 #include <get-errno.h>
 #include <quotearg.h>
 #include "muscle_tab.h"
 #include "output.h"
 #include "reader.h"
 #include "muscle_tab.h"
 #include "output.h"
 #include "reader.h"
+#include "scan-code.h"    /* max_left_semantic_context */
+#include "scan-skel.h"
 #include "symtab.h"
 #include "tables.h"
 
 #include "symtab.h"
 #include "tables.h"
 
-/* From src/scan-skel.l. */
-void scan_skel (FILE *);
-
 
 static struct obstack format_obstack;
 
 
 static struct obstack format_obstack;
 
-bool error_verbose = false;
-
-
 
 /*-------------------------------------------------------------------.
 | Create a function NAME which associates to the muscle NAME the     |
 
 /*-------------------------------------------------------------------.
 | Create a function NAME which associates to the muscle NAME the     |
@@ -145,6 +142,7 @@ escaped_output (FILE *out, char const *string)
 static void
 prepare_symbols (void)
 {
 static void
 prepare_symbols (void)
 {
+  MUSCLE_INSERT_BOOL ("token_table", token_table_flag);
   MUSCLE_INSERT_INT ("tokens_number", ntokens);
   MUSCLE_INSERT_INT ("nterms_number", nvars);
   MUSCLE_INSERT_INT ("undef_token_number", undeftoken->number);
   MUSCLE_INSERT_INT ("tokens_number", ntokens);
   MUSCLE_INSERT_INT ("nterms_number", nvars);
   MUSCLE_INSERT_INT ("undef_token_number", undeftoken->number);
@@ -179,9 +177,7 @@ prepare_symbols (void)
        obstack_1grow (&format_obstack, ',');
        j += width;
       }
        obstack_1grow (&format_obstack, ',');
        j += width;
       }
-    /* Add a NULL entry to list of tokens (well, 0, as NULL might not be
-       defined).  */
-    obstack_sgrow (&format_obstack, " 0");
+    obstack_sgrow (&format_obstack, " ]b4_null[");
 
     /* Finish table and store. */
     obstack_1grow (&format_obstack, 0);
 
     /* Finish table and store. */
     obstack_1grow (&format_obstack, 0);
@@ -240,8 +236,7 @@ prepare_rules (void)
       /* Merger-function index (GLR).  */
       merger[r] = rules[r].merger;
     }
       /* Merger-function index (GLR).  */
       merger[r] = rules[r].merger;
     }
-  if (i != nritems)
-    abort ();
+  aver (i == nritems);
 
   muscle_insert_item_number_table ("rhs", rhs, ritem[0], 1, nritems);
   muscle_insert_unsigned_int_table ("prhs", prhs, 0, 0, nrules);
 
   muscle_insert_item_number_table ("rhs", rhs, ritem[0], 1, nritems);
   muscle_insert_unsigned_int_table ("prhs", prhs, 0, 0, nrules);
@@ -294,20 +289,16 @@ user_actions_output (FILE *out)
 {
   rule_number r;
 
 {
   rule_number r;
 
-  fputs ("m4_define([b4_actions], \n[[", out);
+  fputs ("m4_define([b4_actions], \n[", out);
   for (r = 0; r < nrules; ++r)
     if (rules[r].action)
       {
   for (r = 0; r < nrules; ++r)
     if (rules[r].action)
       {
-       fprintf (out, "  case %d:\n", r + 1);
-
-       fprintf (out, "]b4_syncline(%d, ",
+       fprintf (out, "b4_case(%d, [b4_syncline(%d, ", r + 1,
                 rules[r].action_location.start.line);
        escaped_output (out, rules[r].action_location.start.file);
                 rules[r].action_location.start.line);
        escaped_output (out, rules[r].action_location.start.file);
-       fprintf (out, ")[\n");
-       fprintf (out, "    %s\n    break;\n\n",
-                rules[r].action);
+       fprintf (out, ")\n[    %s]])\n\n", rules[r].action);
       }
       }
-  fputs ("]])\n\n", out);
+  fputs ("])\n\n", out);
 }
 
 /*--------------------------------------.
 }
 
 /*--------------------------------------.
@@ -352,8 +343,7 @@ token_definitions_output (FILE *out)
       /* At this stage, if there are literal aliases, they are part of
         SYMBOLS, so we should not find symbols which are the aliases
         here.  */
       /* At this stage, if there are literal aliases, they are part of
         SYMBOLS, so we should not find symbols which are the aliases
         here.  */
-      if (number == USER_NUMBER_ALIAS)
-       abort ();
+      aver (number != USER_NUMBER_ALIAS);
 
       /* Skip error token.  */
       if (sym == errtoken)
 
       /* Skip error token.  */
       if (sym == errtoken)
@@ -383,68 +373,41 @@ token_definitions_output (FILE *out)
 }
 
 
 }
 
 
-/*---------------------------------------.
-| Output the symbol destructors to OUT.  |
-`---------------------------------------*/
+/*---------------------------------------------------.
+| Output the symbol destructors or printers to OUT.  |
+`---------------------------------------------------*/
 
 static void
 
 static void
-symbol_destructors_output (FILE *out)
+symbol_code_props_output (FILE *out, char const *what,
+                          code_props const *(*get)(symbol const *))
 {
   int i;
   char const *sep = "";
 
 {
   int i;
   char const *sep = "";
 
-  fputs ("m4_define([b4_symbol_destructors], \n[", out);
+  fputs ("m4_define([b4_symbol_", out);
+  fputs (what, out);
+  fputs ("], \n[", out);
   for (i = 0; i < nsyms; ++i)
   for (i = 0; i < nsyms; ++i)
-    if (symbols[i]->destructor)
-      {
-       symbol *sym = symbols[i];
-
-       /* Filename, lineno,
-          Symbol-name, Symbol-number,
-          destructor, optional typename.  */
-       fprintf (out, "%s[", sep);
-       sep = ",\n";
-       escaped_output (out, sym->destructor_location.start.file);
-       fprintf (out, ", %d, ", sym->destructor_location.start.line);
-       escaped_output (out, sym->tag);
-       fprintf (out, ", %d, [[%s]]", sym->number, sym->destructor);
-       if (sym->type_name)
-         fprintf (out, ", [[%s]]", sym->type_name);
-       fputc (']', out);
-      }
-  fputs ("])\n\n", out);
-}
-
-
-/*------------------------------------.
-| Output the symbol printers to OUT.  |
-`------------------------------------*/
-
-static void
-symbol_printers_output (FILE *out)
-{
-  int i;
-  char const *sep = "";
-
-  fputs ("m4_define([b4_symbol_printers], \n[", out);
-  for (i = 0; i < nsyms; ++i)
-    if (symbols[i]->printer)
-      {
-       symbol *sym = symbols[i];
-
-       /* Filename, lineno,
-          Symbol-name, Symbol-number,
-          printer, optional typename.  */
-       fprintf (out, "%s[", sep);
-       sep = ",\n";
-       escaped_output (out, sym->printer_location.start.file);
-       fprintf (out, ", %d, ", sym->printer_location.start.line);
-       escaped_output (out, sym->tag);
-       fprintf (out, ", %d, [[%s]]", sym->number, sym->printer);
-       if (sym->type_name)
-         fprintf (out, ", [[%s]]", sym->type_name);
-       fputc (']', out);
-      }
+    {
+      symbol *sym = symbols[i];
+      char const *code = (*get) (sym)->code;
+      if (code)
+        {
+          location loc = (*get) (sym)->location;
+          /* Filename, lineno,
+             Symbol-name, Symbol-number,
+             code, optional typename.  */
+          fprintf (out, "%s[", sep);
+          sep = ",\n";
+          escaped_output (out, loc.start.file);
+          fprintf (out, ", %d, ", loc.start.line);
+          escaped_output (out, sym->tag);
+          fprintf (out, ", %d, [[%s]]", sym->number, code);
+          if (sym->type_name)
+            fprintf (out, ", [[%s]]", sym->type_name);
+          fputc (']', out);
+        }
+    }
   fputs ("])\n\n", out);
 }
 
   fputs ("])\n\n", out);
 }
 
@@ -453,7 +416,7 @@ static void
 prepare_actions (void)
 {
   /* Figure out the actions for the specified state, indexed by
 prepare_actions (void)
 {
   /* Figure out the actions for the specified state, indexed by
-     look-ahead token type.  */
+     lookahead token type.  */
 
   muscle_insert_rule_number_table ("defact", yydefact,
                                   yydefact[0], 1, nstates);
 
   muscle_insert_rule_number_table ("defact", yydefact,
                                   yydefact[0], 1, nstates);
@@ -507,7 +470,7 @@ output_skeleton (void)
   FILE *in;
   FILE *out;
   int filter_fd[2];
   FILE *in;
   FILE *out;
   int filter_fd[2];
-  char const *argv[6];
+  char const *argv[7];
   pid_t pid;
 
   /* Compute the names of the package data dir and skeleton file.
   pid_t pid;
 
   /* Compute the names of the package data dir and skeleton file.
@@ -515,8 +478,9 @@ output_skeleton (void)
      installation.  A faulty installation can cause deadlock, so a
      cheap sanity check is worthwhile.  */
   char const m4sugar[] = "m4sugar/m4sugar.m4";
      installation.  A faulty installation can cause deadlock, so a
      cheap sanity check is worthwhile.  */
   char const m4sugar[] = "m4sugar/m4sugar.m4";
+  char const m4bison[] = "bison.m4";
   char *full_m4sugar;
   char *full_m4sugar;
-  char *full_cm4;
+  char *full_m4bison;
   char *full_skeleton;
   char const *p;
   char const *m4 = (p = getenv ("M4")) ? p : M4;
   char *full_skeleton;
   char const *p;
   char const *m4 = (p = getenv ("M4")) ? p : M4;
@@ -528,37 +492,42 @@ output_skeleton (void)
   full_skeleton = xmalloc (pkgdatadirlen + 1
                           + (skeleton_size < sizeof m4sugar
                              ? sizeof m4sugar : skeleton_size));
   full_skeleton = xmalloc (pkgdatadirlen + 1
                           + (skeleton_size < sizeof m4sugar
                              ? sizeof m4sugar : skeleton_size));
-  strcpy (full_skeleton, pkgdatadir);
+  strncpy (full_skeleton, pkgdatadir, pkgdatadirlen);
   full_skeleton[pkgdatadirlen] = '/';
   strcpy (full_skeleton + pkgdatadirlen + 1, m4sugar);
   full_m4sugar = xstrdup (full_skeleton);
   full_skeleton[pkgdatadirlen] = '/';
   strcpy (full_skeleton + pkgdatadirlen + 1, m4sugar);
   full_m4sugar = xstrdup (full_skeleton);
-  strcpy (full_skeleton + pkgdatadirlen + 1, "c.m4");
-  full_cm4 = xstrdup (full_skeleton);
-  strcpy (full_skeleton + pkgdatadirlen + 1, skeleton);
+  strcpy (full_skeleton + pkgdatadirlen + 1, m4bison);
+  full_m4bison = xstrdup (full_skeleton);
+  if (strchr (skeleton, '/'))
+    strcpy (full_skeleton, skeleton);
+  else
+    strcpy (full_skeleton + pkgdatadirlen + 1, skeleton);
   xfclose (xfopen (full_m4sugar, "r"));
 
   /* Create an m4 subprocess connected to us via two pipes.  */
 
   if (trace_flag & trace_tools)
     fprintf (stderr, "running: %s %s - %s %s\n",
   xfclose (xfopen (full_m4sugar, "r"));
 
   /* Create an m4 subprocess connected to us via two pipes.  */
 
   if (trace_flag & trace_tools)
     fprintf (stderr, "running: %s %s - %s %s\n",
-            m4, full_m4sugar, full_cm4, full_skeleton);
+            m4, full_m4sugar, full_m4bison, full_skeleton);
 
   argv[0] = m4;
   argv[1] = full_m4sugar;
   argv[2] = "-";
 
   argv[0] = m4;
   argv[1] = full_m4sugar;
   argv[2] = "-";
-  argv[3] = full_cm4;
+  argv[3] = full_m4bison;
   argv[4] = full_skeleton;
   argv[4] = full_skeleton;
-  argv[5] = NULL;
+  argv[5] = trace_flag & trace_m4 ? "-dV" : NULL;
+  argv[6] = NULL;
 
   init_subpipe ();
   pid = create_subpipe (argv, filter_fd);
 
   init_subpipe ();
   pid = create_subpipe (argv, filter_fd);
+  free (full_m4bison);
   free (full_m4sugar);
   free (full_m4sugar);
-  free (full_cm4);
   free (full_skeleton);
 
   out = fdopen (filter_fd[0], "w");
   if (! out)
   free (full_skeleton);
 
   out = fdopen (filter_fd[0], "w");
   if (! out)
-    error (EXIT_FAILURE, get_errno (), "fdopen");
+    error (EXIT_FAILURE, get_errno (),
+          "fdopen");
 
   /* Output the definitions of all the muscles.  */
   fputs ("m4_init()\n", out);
 
   /* Output the definitions of all the muscles.  */
   fputs ("m4_init()\n", out);
@@ -566,20 +535,19 @@ output_skeleton (void)
   user_actions_output (out);
   merger_output (out);
   token_definitions_output (out);
   user_actions_output (out);
   merger_output (out);
   token_definitions_output (out);
-  symbol_destructors_output (out);
-  symbol_printers_output (out);
+  symbol_code_props_output (out, "destructors", &symbol_destructor_get);
+  symbol_code_props_output (out, "printers", &symbol_printer_get);
 
   muscles_m4_output (out);
 
   muscles_m4_output (out);
-
-  fputs ("m4_wrap([m4_divert_pop(0)])\n", out);
-  fputs ("m4_divert_push(0)dnl\n", out);
   xfclose (out);
 
   /* Read and process m4's output.  */
   timevar_push (TV_M4);
   xfclose (out);
 
   /* Read and process m4's output.  */
   timevar_push (TV_M4);
+  end_of_output_subpipe (pid, filter_fd);
   in = fdopen (filter_fd[1], "r");
   if (! in)
   in = fdopen (filter_fd[1], "r");
   if (! in)
-    error (EXIT_FAILURE, get_errno (), "fdopen");
+    error (EXIT_FAILURE, get_errno (),
+          "fdopen");
   scan_skel (in);
   xfclose (in);
   reap_subpipe (pid, m4);
   scan_skel (in);
   xfclose (in);
   reap_subpipe (pid, m4);
@@ -589,34 +557,62 @@ output_skeleton (void)
 static void
 prepare (void)
 {
 static void
 prepare (void)
 {
+  /* BISON_USE_PUSH_FOR_PULL is for the test suite and should not be documented
+     for the user.  */
+  char const *use_push_for_pull_env = getenv ("BISON_USE_PUSH_FOR_PULL");
+  bool use_push_for_pull_flag = false;
+  if (use_push_for_pull_env != NULL
+      && use_push_for_pull_env[0] != '\0'
+      && 0 != strcmp (use_push_for_pull_env, "0"))
+    use_push_for_pull_flag = true;
+
   /* Flags. */
   /* Flags. */
-  MUSCLE_INSERT_BOOL ("debug", debug_flag);
+  MUSCLE_INSERT_BOOL ("debug_flag", debug_flag);
   MUSCLE_INSERT_BOOL ("defines_flag", defines_flag);
   MUSCLE_INSERT_BOOL ("defines_flag", defines_flag);
-  MUSCLE_INSERT_BOOL ("error_verbose", error_verbose);
+  MUSCLE_INSERT_BOOL ("error_verbose_flag", error_verbose);
+  MUSCLE_INSERT_BOOL ("glr_flag", glr_parser);
   MUSCLE_INSERT_BOOL ("locations_flag", locations_flag);
   MUSCLE_INSERT_BOOL ("locations_flag", locations_flag);
-  MUSCLE_INSERT_BOOL ("pure", pure_parser);
+  MUSCLE_INSERT_BOOL ("nondeterministic_flag", nondeterministic_parser);
+  MUSCLE_INSERT_BOOL ("pull_flag", pull_parser);
+  MUSCLE_INSERT_BOOL ("pure_flag", pure_parser);
+  MUSCLE_INSERT_BOOL ("push_flag", push_parser);
   MUSCLE_INSERT_BOOL ("synclines_flag", !no_lines_flag);
   MUSCLE_INSERT_BOOL ("synclines_flag", !no_lines_flag);
+  MUSCLE_INSERT_BOOL ("tag_seen_flag", tag_seen);
+  MUSCLE_INSERT_BOOL ("use_push_for_pull_flag", use_push_for_pull_flag);
+  MUSCLE_INSERT_BOOL ("yacc_flag", yacc_flag);
 
   /* File names.  */
 
   /* File names.  */
-  MUSCLE_INSERT_STRING ("prefix", spec_name_prefix ? spec_name_prefix : "yy");
-
-  /* User Code.  */
-  obstack_1grow (&pre_prologue_obstack, 0);
-  obstack_1grow (&post_prologue_obstack, 0);
-  muscle_insert ("pre_prologue", obstack_finish (&pre_prologue_obstack));
-  muscle_insert ("post_prologue", obstack_finish (&post_prologue_obstack));
-
-  /* Find the right skeleton file.  */
-  if (!skeleton)
-    {
-      if (glr_parser || nondeterministic_parser)
-       skeleton = "glr.c";
-      else
-       skeleton = "yacc.c";
-    }
-
-  /* Parse the skeleton file and output the needed parsers.  */
-  MUSCLE_INSERT_C_STRING ("skeleton", skeleton);
+  if (spec_name_prefix)
+    MUSCLE_INSERT_STRING ("prefix", spec_name_prefix);
+
+  MUSCLE_INSERT_STRING ("file_name_all_but_ext", all_but_ext);
+
+#define DEFINE(Name) MUSCLE_INSERT_STRING (#Name, Name ? Name : "")
+  DEFINE (dir_prefix);
+  DEFINE (parser_file_name);
+  DEFINE (spec_defines_file);
+  DEFINE (spec_file_prefix);
+  DEFINE (spec_graph_file);
+  DEFINE (spec_name_prefix);
+  DEFINE (spec_outfile);
+  DEFINE (spec_verbose_file);
+#undef DEFINE
+
+  /* Find the right skeleton file, and add muscles about the skeletons.  */
+  if (skeleton)
+    MUSCLE_INSERT_C_STRING ("skeleton", skeleton);
+  else
+    skeleton = language->skeleton;
+
+  /* About the skeletons.  */
+  {
+    char const *pkgdatadir = getenv ("BISON_PKGDATADIR");
+    /* b4_pkgdatadir is used inside m4_include in the skeletons, so digraphs
+       would never be expanded.  Hopefully no one has M4-special characters in
+       his Bison installation path.  */
+    MUSCLE_INSERT_STRING_RAW ("pkgdatadir",
+                              pkgdatadir ? pkgdatadir : PKGDATADIR);
+  }
 }
 
 
 }
 
 
@@ -640,6 +636,4 @@ output (void)
   output_skeleton ();
 
   obstack_free (&format_obstack, NULL);
   output_skeleton ();
 
   obstack_free (&format_obstack, NULL);
-  obstack_free (&pre_prologue_obstack, NULL);
-  obstack_free (&post_prologue_obstack, NULL);
 }
 }