X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/945e396c8a4fcaa24f2445766a7098bf3c60f904..fe1b448ada5e3a79ae3f523e08b5004396f30ca9:/src/output.c
diff --git a/src/output.c b/src/output.c
index b30fe4b9..31bfd12d 100644
--- a/src/output.c
+++ b/src/output.c
@@ -1,24 +1,22 @@
/* Output the generated parsing program for Bison.
Copyright (C) 1984, 1986, 1989, 1992, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
- Bison is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
- Bison is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with Bison; see the file COPYING. If not, write to the Free
- Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
+ along with this program. If not, see . */
#include
#include "system.h"
@@ -145,6 +143,7 @@ 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 ("symbols_number", nsyms);
MUSCLE_INSERT_INT ("undef_token_number", undeftoken->number);
MUSCLE_INSERT_INT ("user_token_number_max", max_user_token_number);
@@ -158,9 +157,12 @@ prepare_symbols (void)
int i;
/* We assume that the table will be output starting at column 2. */
int j = 2;
+ struct quoting_options *qo = clone_quoting_options (0);
+ set_quoting_style (qo, c_quoting_style);
+ set_quoting_flags (qo, QA_SPLIT_TRIGRAPHS);
for (i = 0; i < nsyms; i++)
{
- char const *cp = quotearg_style (c_quoting_style, symbols[i]->tag);
+ char *cp = quotearg_alloc (symbols[i]->tag, -1, qo);
/* Width of the next token, including the two quotes, the
comma and the space. */
int width = strlen (cp) + 2;
@@ -174,9 +176,11 @@ prepare_symbols (void)
if (i)
obstack_1grow (&format_obstack, ' ');
MUSCLE_OBSTACK_SGROW (&format_obstack, cp);
+ free (cp);
obstack_1grow (&format_obstack, ',');
j += width;
}
+ free (qo);
obstack_sgrow (&format_obstack, " ]b4_null[");
/* Finish table and store. */
@@ -279,6 +283,73 @@ prepare_states (void)
}
+/*-------------------------------------------------------.
+| Compare two symbols by type-name, and then by number. |
+`-------------------------------------------------------*/
+
+int
+symbol_type_name_cmp (const symbol **lhs, const symbol **rhs)
+{
+ int res = UNIQSTR_CMP((*lhs)->type_name, (*rhs)->type_name);
+ if (res)
+ return res;
+ return (*lhs)->number - (*rhs)->number;
+}
+
+
+/*----------------------------------------------------------------.
+| Return a (malloc'ed) table of the symbols sorted by type-name. |
+`----------------------------------------------------------------*/
+
+static symbol **
+symbols_by_type_name ()
+{
+ typedef int (*qcmp_type) (const void *, const void *);
+ symbol **res = xmemdup (symbols, nsyms * sizeof *res);
+ qsort (res, nsyms, sizeof *res, (qcmp_type) &symbol_type_name_cmp);
+ return res;
+}
+
+
+/*------------------------------------------------------------------.
+| Define b4_type_names, which is a list of (lists of the numbers of |
+| symbols with same type-name). |
+`------------------------------------------------------------------*/
+
+static void
+type_names_output (FILE *out)
+{
+ int i;
+ symbol **syms = symbols_by_type_name ();
+ fputs ("m4_define([b4_type_names],\n[", out);
+ for (i = 0; i < nsyms; /* nothing */)
+ {
+ // The index of the first symbol of the current type-name.
+ int i0 = i;
+ fputs (i ? ",\n[" : "[", out);
+ for (; i < nsyms && syms[i]->type_name == syms[i0]->type_name; ++i)
+ fprintf (out, "%s%d", i != i0 ? ", " : "", syms[i]->number);
+ fputs ("]", out);
+ }
+ fputs ("])\n\n", out);
+ free (syms);
+}
+
+
+/*-------------------------------------.
+| The list of all the symbol numbers. |
+`-------------------------------------*/
+
+static void
+symbol_numbers_output (FILE *out)
+{
+ int i;
+ fputs ("m4_define([b4_symbol_numbers],\n[", out);
+ for (i = 0; i < nsyms; ++i)
+ fprintf (out, "%s[%d]", i ? ", " : "", i);
+ fputs ("])\n\n", out);
+}
+
/*---------------------------------.
| Output the user actions to OUT. |
@@ -301,9 +372,9 @@ user_actions_output (FILE *out)
fputs ("])\n\n", out);
}
-/*--------------------------------------.
-| Output the merge functions to OUT. |
-`--------------------------------------*/
+/*------------------------------------.
+| Output the merge functions to OUT. |
+`------------------------------------*/
static void
merger_output (FILE *out)
@@ -324,6 +395,60 @@ merger_output (FILE *out)
fputs ("]])\n\n", out);
}
+
+/*---------------------------------------.
+| Output the symbol definitions to OUT. |
+`---------------------------------------*/
+
+static void
+symbol_definitions_output (FILE *out)
+{
+ int i;
+ for (i = 0; i < nsyms; ++i)
+ {
+ symbol *sym = symbols[i];
+ const char *key;
+ const char *value;
+
+#define SET_KEY(Entry) \
+ obstack_fgrow2 (&format_obstack, "symbol(%d, %s)", i, Entry); \
+ obstack_1grow (&format_obstack, 0); \
+ key = obstack_finish (&format_obstack);
+
+ // Whether the symbol has an identifier.
+ value = symbol_id_get (sym);
+ SET_KEY("has_id");
+ MUSCLE_INSERT_INT (key, !!value);
+
+ // Its identifier.
+ SET_KEY("id");
+ MUSCLE_INSERT_STRING (key, value ? value : "");
+
+ // Its tag. Typically for documentation purpose.
+ SET_KEY("tag");
+ MUSCLE_INSERT_STRING (key, sym->tag);
+
+ SET_KEY("user_number");
+ MUSCLE_INSERT_INT (key, sym->user_token_number);
+
+ SET_KEY("is_token");
+ MUSCLE_INSERT_INT (key,
+ i < ntokens && sym != errtoken && sym != undeftoken);
+
+ SET_KEY("number");
+ MUSCLE_INSERT_INT (key, sym->number);
+
+ SET_KEY("has_type");
+ MUSCLE_INSERT_INT (key, !!sym->type_name);
+
+ SET_KEY("type");
+ MUSCLE_INSERT_STRING (key, sym->type_name ? sym->type_name : "");
+
+#undef SET_KEY
+ }
+}
+
+
/*--------------------------------------.
| Output the tokens definition to OUT. |
`--------------------------------------*/
@@ -373,70 +498,41 @@ token_definitions_output (FILE *out)
}
-/*---------------------------------------.
-| Output the symbol destructors to OUT. |
-`---------------------------------------*/
+/*---------------------------------------------------.
+| Output the symbol destructors or printers to OUT. |
+`---------------------------------------------------*/
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 = "";
- 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)
- if (symbol_destructor_get (symbols[i]))
- {
- symbol *sym = symbols[i];
-
- /* Filename, lineno,
- Symbol-name, Symbol-number,
- destructor, optional typename. */
- fprintf (out, "%s[", sep);
- sep = ",\n";
- escaped_output (out, symbol_destructor_location_get (sym).start.file);
- fprintf (out, ", %d, ",
- symbol_destructor_location_get (sym).start.line);
- escaped_output (out, sym->tag);
- fprintf (out, ", %d, [[%s]]", sym->number,
- symbol_destructor_get (sym));
- 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 (symbol_printer_get (symbols[i]))
- {
- symbol *sym = symbols[i];
-
- /* Filename, lineno,
- Symbol-name, Symbol-number,
- printer, optional typename. */
- fprintf (out, "%s[", sep);
- sep = ",\n";
- escaped_output (out, symbol_printer_location_get (sym).start.file);
- fprintf (out, ", %d, ", symbol_printer_location_get (sym).start.line);
- escaped_output (out, sym->tag);
- fprintf (out, ", %d, [[%s]]", sym->number, symbol_printer_get (sym));
- 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);
}
@@ -488,6 +584,26 @@ prepare_actions (void)
0, 1, conflict_list_cnt);
}
+
+/*--------------------------------------------.
+| Output the definitions of all the muscles. |
+`--------------------------------------------*/
+
+static void
+muscles_output (FILE *out)
+{
+ fputs ("m4_init()\n", out);
+ merger_output (out);
+ symbol_code_props_output (out, "destructors", &symbol_destructor_get);
+ symbol_code_props_output (out, "printers", &symbol_printer_get);
+ symbol_definitions_output (out);
+ symbol_numbers_output (out);
+ token_definitions_output (out);
+ type_names_output (out);
+ user_actions_output (out);
+ // Must be last.
+ muscles_m4_output (out);
+}
/*---------------------------.
| Call the skeleton parser. |
@@ -497,15 +613,11 @@ static void
output_skeleton (void)
{
FILE *in;
- FILE *out;
int filter_fd[2];
- char const *argv[7];
+ char const *argv[9];
pid_t pid;
- /* Compute the names of the package data dir and skeleton file.
- Test whether m4sugar.m4 is readable, to check for proper
- installation. A faulty installation can cause deadlock, so a
- cheap sanity check is worthwhile. */
+ /* Compute the names of the package data dir and skeleton files. */
char const m4sugar[] = "m4sugar/m4sugar.m4";
char const m4bison[] = "bison.m4";
char *full_m4sugar;
@@ -513,7 +625,7 @@ output_skeleton (void)
char *full_skeleton;
char const *p;
char const *m4 = (p = getenv ("M4")) ? p : M4;
- char const *pkgdatadir = (p = getenv ("BISON_PKGDATADIR")) ? p : PKGDATADIR;
+ char const *pkgdatadir = compute_pkgdatadir ();
size_t skeleton_size = strlen (skeleton) + 1;
size_t pkgdatadirlen = strlen (pkgdatadir);
while (pkgdatadirlen && pkgdatadir[pkgdatadirlen - 1] == '/')
@@ -521,54 +633,83 @@ output_skeleton (void)
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);
strcpy (full_skeleton + pkgdatadirlen + 1, m4bison);
full_m4bison = xstrdup (full_skeleton);
- strcpy (full_skeleton + pkgdatadirlen + 1, skeleton);
+ if (strchr (skeleton, '/'))
+ strcpy (full_skeleton, skeleton);
+ else
+ strcpy (full_skeleton + pkgdatadirlen + 1, skeleton);
+
+ /* Test whether m4sugar.m4 is readable, to check for proper
+ installation. A faulty installation can cause deadlock, so a
+ cheap sanity check is worthwhile. */
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_m4bison, full_skeleton);
+ m4, full_m4sugar, full_m4bison, full_skeleton);
- argv[0] = m4;
- argv[1] = full_m4sugar;
- argv[2] = "-";
- argv[3] = full_m4bison;
- argv[4] = full_skeleton;
- argv[5] = trace_flag & trace_m4 ? "-dV" : NULL;
- argv[6] = NULL;
+ /* Some future version of GNU M4 (most likely 1.6) may treat the -dV in a
+ position-dependent manner. Keep it as the first argument so that all
+ files are traced.
+ See the thread starting at
+
+ for details. */
+ {
+ int i = 0;
+ argv[i++] = m4;
+ argv[i++] = "-I";
+ argv[i++] = pkgdatadir;
+ if (trace_flag & trace_m4)
+ argv[i++] = "-dV";
+ argv[i++] = full_m4sugar;
+ argv[i++] = "-";
+ argv[i++] = full_m4bison;
+ argv[i++] = full_skeleton;
+ argv[i++] = NULL;
+ }
+ /* When POSIXLY_CORRECT is set, some future versions of GNU M4 (most likely
+ 2.0) may drop some of the GNU extensions that Bison's skeletons depend
+ upon. So that the next release of Bison is forward compatible with those
+ future versions of GNU M4, we unset POSIXLY_CORRECT here.
+
+ FIXME: A user might set POSIXLY_CORRECT to affect processes run from
+ macros like m4_syscmd in a custom skeleton. For now, Bison makes no
+ promises about the behavior of custom skeletons, so this scenario is not a
+ concern. However, we eventually want to eliminate this shortcoming. The
+ next release of GNU M4 (1.4.12 or 1.6) will accept the -g command-line
+ option as a no-op, and later releases will accept it to indicate that
+ POSIXLY_CORRECT should be ignored. Once the GNU M4 versions that accept
+ -g are pervasive, Bison should use -g instead of unsetting
+ POSIXLY_CORRECT.
+
+ See the thread starting at
+
+ for details. */
+ unsetenv ("POSIXLY_CORRECT");
init_subpipe ();
pid = create_subpipe (argv, filter_fd);
- free (full_m4bison);
free (full_m4sugar);
+ free (full_m4bison);
free (full_skeleton);
- out = fdopen (filter_fd[0], "w");
- if (! out)
- error (EXIT_FAILURE, get_errno (),
- "fdopen");
-
- /* Output the definitions of all the muscles. */
- fputs ("m4_init()\n", out);
-
- user_actions_output (out);
- merger_output (out);
- token_definitions_output (out);
- symbol_destructors_output (out);
- symbol_printers_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);
+ if (trace_flag & trace_muscles)
+ muscles_output (stderr);
+ {
+ FILE *out = fdopen (filter_fd[0], "w");
+ if (! out)
+ error (EXIT_FAILURE, get_errno (),
+ "fdopen");
+ muscles_output (out);
+ xfclose (out);
+ }
/* Read and process m4's output. */
timevar_push (TV_M4);
@@ -602,12 +743,9 @@ prepare (void)
MUSCLE_INSERT_BOOL ("glr_flag", glr_parser);
MUSCLE_INSERT_BOOL ("locations_flag", locations_flag);
MUSCLE_INSERT_BOOL ("nondeterministic_flag", nondeterministic_parser);
- MUSCLE_INSERT_BOOL ("pull_flag", pull_parser);
- MUSCLE_INSERT_BOOL ("pure_flag", pure_parser);
- MUSCLE_INSERT_BOOL ("use_push_for_pull_flag", use_push_for_pull_flag);
- MUSCLE_INSERT_BOOL ("push_flag", push_parser);
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. */
@@ -627,12 +765,6 @@ prepare (void)
DEFINE (spec_verbose_file);
#undef DEFINE
- /* 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, and add muscles about the skeletons. */
if (skeleton)
MUSCLE_INSERT_C_STRING ("skeleton", skeleton);
@@ -641,12 +773,10 @@ prepare (void)
/* 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);
+ MUSCLE_INSERT_STRING_RAW ("pkgdatadir", compute_pkgdatadir ());
}
}
@@ -671,6 +801,11 @@ output (void)
output_skeleton ();
obstack_free (&format_obstack, NULL);
- obstack_free (&pre_prologue_obstack, NULL);
- obstack_free (&post_prologue_obstack, NULL);
+}
+
+char const *
+compute_pkgdatadir (void)
+{
+ char const *pkgdatadir = getenv ("BISON_PKGDATADIR");
+ return pkgdatadir ? pkgdatadir : PKGDATADIR;
}