X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/9789acf09124eb5ffbe5f0737261aec91b32ebd4..b9278c7d174c1be5d7482343c5e433f428657ed0:/src/output.c diff --git a/src/output.c b/src/output.c index 562918c0..c64c7aa0 100644 --- a/src/output.c +++ b/src/output.c @@ -1,7 +1,7 @@ /* Output the generated parsing program for Bison. - Copyright (C) 1984, 1986, 1989, 1992, 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + Copyright (C) 1984, 1986, 1989, 1992, 2000-2012 Free Software + Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -21,12 +21,14 @@ #include #include "system.h" +#include #include -#include +#include #include #include -#include +#include #include +#include #include "complain.h" #include "files.h" @@ -40,8 +42,6 @@ #include "symtab.h" #include "tables.h" -# define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array)) - static struct obstack format_obstack; @@ -53,51 +53,48 @@ static struct obstack format_obstack; `-------------------------------------------------------------------*/ -#define GENERATE_MUSCLE_INSERT_TABLE(Name, Type) \ - \ -static void \ -Name (char const *name, \ - Type *table_data, \ - Type first, \ - int begin, \ - int end) \ -{ \ - Type min = first; \ - Type max = first; \ - long int lmin; \ - long int lmax; \ - int i; \ - int j = 1; \ - \ - obstack_fgrow1 (&format_obstack, "%6d", first); \ - for (i = begin; i < end; ++i) \ - { \ - obstack_1grow (&format_obstack, ','); \ - if (j >= 10) \ - { \ - obstack_sgrow (&format_obstack, "\n "); \ - j = 1; \ - } \ - else \ - ++j; \ - obstack_fgrow1 (&format_obstack, "%6d", table_data[i]); \ - if (table_data[i] < min) \ - min = table_data[i]; \ - if (max < table_data[i]) \ - max = table_data[i]; \ - } \ - obstack_1grow (&format_obstack, 0); \ - muscle_insert (name, obstack_finish (&format_obstack)); \ - \ - lmin = min; \ - lmax = max; \ - /* Build `NAME_min' and `NAME_max' in the obstack. */ \ - obstack_fgrow1 (&format_obstack, "%s_min", name); \ - obstack_1grow (&format_obstack, 0); \ - MUSCLE_INSERT_LONG_INT (obstack_finish (&format_obstack), lmin); \ - obstack_fgrow1 (&format_obstack, "%s_max", name); \ - obstack_1grow (&format_obstack, 0); \ - MUSCLE_INSERT_LONG_INT (obstack_finish (&format_obstack), lmax); \ +#define GENERATE_MUSCLE_INSERT_TABLE(Name, Type) \ + \ +static void \ +Name (char const *name, \ + Type *table_data, \ + Type first, \ + int begin, \ + int end) \ +{ \ + Type min = first; \ + Type max = first; \ + long int lmin; \ + long int lmax; \ + int i; \ + int j = 1; \ + \ + obstack_printf (&format_obstack, "%6d", first); \ + for (i = begin; i < end; ++i) \ + { \ + obstack_1grow (&format_obstack, ','); \ + if (j >= 10) \ + { \ + obstack_sgrow (&format_obstack, "\n "); \ + j = 1; \ + } \ + else \ + ++j; \ + obstack_printf (&format_obstack, "%6d", table_data[i]); \ + if (table_data[i] < min) \ + min = table_data[i]; \ + if (max < table_data[i]) \ + max = table_data[i]; \ + } \ + muscle_insert (name, obstack_finish0 (&format_obstack)); \ + \ + lmin = min; \ + lmax = max; \ + /* Build `NAME_min' and `NAME_max' in the obstack. */ \ + obstack_printf (&format_obstack, "%s_min", name); \ + MUSCLE_INSERT_LONG_INT (obstack_finish0 (&format_obstack), lmin); \ + obstack_printf (&format_obstack, "%s_max", name); \ + MUSCLE_INSERT_LONG_INT (obstack_finish0 (&format_obstack), lmax); \ } GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_unsigned_int_table, unsigned int) @@ -108,29 +105,39 @@ GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_symbol_number_table, symbol_number) GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_state_number_table, state_number) -/*--------------------------------------------------------------------. -| Print to OUT a representation of STRING escaped both for C and M4. | -`--------------------------------------------------------------------*/ +/*----------------------------------------------------------------. +| Print to OUT a representation of CP quoted and escaped for M4. | +`----------------------------------------------------------------*/ static void -escaped_output (FILE *out, char const *string) +quoted_output (FILE *out, char const *cp) { - char const *p; fprintf (out, "[["); - for (p = quotearg_style (c_quoting_style, string); *p; p++) - switch (*p) + for (; *cp; cp++) + switch (*cp) { case '$': fputs ("$][", out); break; case '@': fputs ("@@", out); break; case '[': fputs ("@{", out); break; case ']': fputs ("@}", out); break; - default: fputc (*p, out); break; + default: fputc (*cp, out); break; } fprintf (out, "]]"); } +/*----------------------------------------------------------------. +| Print to OUT a representation of STRING quoted and escaped both | +| for C and M4. | +`----------------------------------------------------------------*/ + +static void +string_output (FILE *out, char const *string) +{ + quoted_output (out, quotearg_style (c_quoting_style, string)); +} + /*------------------------------------------------------------------. | Prepare the muscles related to the symbols: translate, tname, and | @@ -140,7 +147,6 @@ escaped_output (FILE *out, char const *string) 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 ("symbols_number", nsyms); @@ -148,9 +154,9 @@ prepare_symbols (void) MUSCLE_INSERT_INT ("user_token_number_max", max_user_token_number); muscle_insert_symbol_number_table ("translate", - token_translations, - token_translations[0], - 1, max_user_token_number + 1); + token_translations, + token_translations[0], + 1, max_user_token_number + 1); /* tname -- token names. */ { @@ -162,30 +168,29 @@ prepare_symbols (void) set_quoting_flags (qo, QA_SPLIT_TRIGRAPHS); for (i = 0; i < nsyms; i++) { - 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; - - if (j + width > 75) - { - obstack_sgrow (&format_obstack, "\n "); - j = 1; - } - - if (i) - obstack_1grow (&format_obstack, ' '); - MUSCLE_OBSTACK_SGROW (&format_obstack, cp); + 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; + + if (j + width > 75) + { + obstack_sgrow (&format_obstack, "\n "); + j = 1; + } + + if (i) + obstack_1grow (&format_obstack, ' '); + obstack_escape (&format_obstack, cp); free (cp); - obstack_1grow (&format_obstack, ','); - j += width; + obstack_1grow (&format_obstack, ','); + j += width; } free (qo); obstack_sgrow (&format_obstack, " ]b4_null["); /* Finish table and store. */ - obstack_1grow (&format_obstack, 0); - muscle_insert ("tname", obstack_finish (&format_obstack)); + muscle_insert ("tname", obstack_finish0 (&format_obstack)); } /* Output YYTOKNUM. */ @@ -195,7 +200,7 @@ prepare_symbols (void) for (i = 0; i < ntokens; ++i) values[i] = symbols[i]->user_token_number; muscle_insert_int_table ("toknum", values, - values[0], 1, ntokens); + values[0], 1, ntokens); free (values); } } @@ -203,7 +208,7 @@ prepare_symbols (void) /*----------------------------------------------------------------. | Prepare the muscles related to the rules: r1, r2, rline, dprec, | -| merger. | +| merger, immediate. | `----------------------------------------------------------------*/ static void @@ -214,6 +219,7 @@ prepare_rules (void) unsigned int *r2 = xnmalloc (nrules, sizeof *r2); int *dprec = xnmalloc (nrules, sizeof *dprec); int *merger = xnmalloc (nrules, sizeof *merger); + int *immediate = xnmalloc (nrules, sizeof *immediate); rule_number r; for (r = 0; r < nrules; ++r) @@ -228,6 +234,8 @@ prepare_rules (void) dprec[r] = rules[r].dprec; /* Merger-function index (GLR). */ merger[r] = rules[r].merger; + /* Immediate reduction flags (GLR). */ + immediate[r] = rules[r].is_predicate; } muscle_insert_unsigned_int_table ("rline", rline, 0, 0, nrules); @@ -235,6 +243,7 @@ prepare_rules (void) muscle_insert_unsigned_int_table ("r2", r2, 0, 0, nrules); muscle_insert_int_table ("dprec", dprec, 0, 0, nrules); muscle_insert_int_table ("merger", merger, 0, 0, nrules); + muscle_insert_int_table ("immediate", immediate, 0, 0, nrules); MUSCLE_INSERT_INT ("rules_number", nrules); MUSCLE_INSERT_INT ("max_left_semantic_context", max_left_semantic_context); @@ -244,6 +253,7 @@ prepare_rules (void) free (r2); free (dprec); free (merger); + free (immediate); } /*--------------------------------------------. @@ -258,7 +268,7 @@ prepare_states (void) for (i = 0; i < nstates; ++i) values[i] = states[i]->accessing_symbol; muscle_insert_symbol_number_table ("stos", values, - 0, 1, nstates); + 0, 1, nstates); free (values); MUSCLE_INSERT_INT ("last", high); @@ -348,10 +358,11 @@ user_actions_output (FILE *out) for (r = 0; r < nrules; ++r) if (rules[r].action) { - 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); - fprintf (out, ")\n[ %s]])\n\n", rules[r].action); + fprintf (out, "b4_%scase(%d, [b4_syncline(%d, ", + rules[r].is_predicate ? "predicate_" : "", + r + 1, rules[r].action_location.start.line); + string_output (out, rules[r].action_location.start.file); + fprintf (out, ")\n[ %s]])\n\n", rules[r].action); } fputs ("])\n\n", out); } @@ -370,11 +381,11 @@ merger_output (FILE *out) for (n = 1, p = merge_functions; p != NULL; n += 1, p = p->next) { if (p->type[0] == '\0') - fprintf (out, " case %d: *yy0 = %s (*yy0, *yy1); break;\n", - n, p->name); + fprintf (out, " case %d: *yy0 = %s (*yy0, *yy1); break;\n", + n, p->name); else - fprintf (out, " case %d: yy0->%s = %s (*yy0, *yy1); break;\n", - n, p->type, p->name); + fprintf (out, " case %d: yy0->%s = %s (*yy0, *yy1); break;\n", + n, p->type, p->name); } fputs ("]])\n\n", out); } @@ -394,10 +405,15 @@ prepare_symbol_definitions (void) 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); +#define SET_KEY(Entry) \ + obstack_printf (&format_obstack, "symbol(%d, %s)", \ + i, Entry); \ + key = obstack_finish0 (&format_obstack); + +#define SET_KEY2(Entry, Suffix) \ + obstack_printf (&format_obstack, "symbol(%d, %s_%s)", \ + i, Entry, Suffix); \ + key = obstack_finish0 (&format_obstack); // Whether the symbol has an identifier. value = symbol_id_get (sym); @@ -428,67 +444,35 @@ prepare_symbol_definitions (void) SET_KEY("type"); MUSCLE_INSERT_STRING (key, sym->type_name ? sym->type_name : ""); -#define CODE_PROP(PropName) \ - do { \ - code_props const *p = symbol_ ## PropName ## _get (sym); \ - SET_KEY("has_" #PropName); \ - MUSCLE_INSERT_INT (key, !!p->code); \ - \ - if (p->code) \ - { \ - SET_KEY(#PropName "_file"); \ - MUSCLE_INSERT_STRING (key, p->location.start.file); \ - \ - SET_KEY(#PropName "_line"); \ - MUSCLE_INSERT_INT (key, p->location.start.line); \ - \ - SET_KEY(#PropName); \ - MUSCLE_INSERT_STRING_RAW (key, p->code); \ - } \ - } while (0) - - CODE_PROP(destructor); - CODE_PROP(printer); -#undef CODE_PROP + { + int j; + for (j = 0; j < CODE_PROPS_SIZE; ++j) + { + /* "printer", not "%printer". */ + char const *pname = code_props_type_string (j) + 1; + code_props const *p = symbol_code_props_get (sym, j); + SET_KEY2("has", pname); + MUSCLE_INSERT_INT (key, !!p->code); + + if (p->code) + { + SET_KEY2(pname, "file"); + MUSCLE_INSERT_STRING (key, p->location.start.file); + + SET_KEY2(pname, "line"); + MUSCLE_INSERT_INT (key, p->location.start.line); + + SET_KEY(pname); + MUSCLE_INSERT_STRING_RAW (key, p->code); + } + } + } +#undef SET_KEY2 #undef SET_KEY } } -/*--------------------------------------. -| Output the tokens definition to OUT. | -`--------------------------------------*/ - -static void -token_definitions_output (FILE *out) -{ - int i; - char const *sep = ""; - - fputs ("m4_define([b4_tokens], \n[", out); - for (i = 0; i < ntokens; ++i) - { - symbol *sym = symbols[i]; - int number = sym->user_token_number; - uniqstr id = symbol_id_get (sym); - - /* At this stage, if there are literal string aliases, they are - part of SYMBOLS, so we should not find their aliased symbols - here. */ - aver (number != USER_NUMBER_HAS_STRING_ALIAS); - - /* Skip error token and tokens without identifier. */ - if (sym != errtoken && id) - { - fprintf (out, "%s[[[%s]], %d]", - sep, id, number); - sep = ",\n"; - } - } - fputs ("])\n\n", out); -} - - static void prepare_actions (void) { @@ -496,30 +480,30 @@ prepare_actions (void) lookahead token type. */ muscle_insert_rule_number_table ("defact", yydefact, - yydefact[0], 1, nstates); + yydefact[0], 1, nstates); /* 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. */ muscle_insert_state_number_table ("defgoto", yydefgoto, - yydefgoto[0], 1, nsyms - ntokens); + yydefgoto[0], 1, nsyms - ntokens); /* Output PACT. */ muscle_insert_base_table ("pact", base, - base[0], 1, nstates); + base[0], 1, nstates); MUSCLE_INSERT_INT ("pact_ninf", base_ninf); /* Output PGOTO. */ muscle_insert_base_table ("pgoto", base, - base[nstates], nstates + 1, nvectors); + base[nstates], nstates + 1, nvectors); muscle_insert_base_table ("table", table, - table[0], 1, high + 1); + table[0], 1, high + 1); MUSCLE_INSERT_INT ("table_ninf", table_ninf); muscle_insert_base_table ("check", check, - check[0], 1, high + 1); + check[0], 1, high + 1); /* GLR parsing slightly modifies YYTABLE and YYCHECK (and thus YYPACT) so that in states with unresolved conflicts, the default @@ -531,9 +515,9 @@ prepare_actions (void) that case. Nevertheless, it seems even better to be able to use the GLR skeletons even without the non-deterministic tables. */ muscle_insert_unsigned_int_table ("conflict_list_heads", conflict_table, - conflict_table[0], 1, high + 1); + conflict_table[0], 1, high + 1); muscle_insert_unsigned_int_table ("conflicting_rules", conflict_list, - 0, 1, conflict_list_cnt); + 0, 1, conflict_list_cnt); } @@ -547,7 +531,6 @@ muscles_output (FILE *out) fputs ("m4_init()\n", out); merger_output (out); symbol_numbers_output (out); - token_definitions_output (out); type_names_output (out); user_actions_output (out); // Must be last. @@ -561,48 +544,28 @@ muscles_output (FILE *out) static void output_skeleton (void) { - FILE *in; int filter_fd[2]; - char const *argv[10]; pid_t pid; /* 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; - char *full_m4bison; - char *full_skeleton; - char const *p; - char const *m4 = (p = getenv ("M4")) ? p : M4; - char const *pkgdatadir = compute_pkgdatadir (); - size_t skeleton_size = strlen (skeleton) + 1; - size_t pkgdatadirlen = strlen (pkgdatadir); - while (pkgdatadirlen && pkgdatadir[pkgdatadirlen - 1] == '/') - pkgdatadirlen--; - full_skeleton = xmalloc (pkgdatadirlen + 1 - + (skeleton_size < sizeof m4sugar - ? sizeof m4sugar : skeleton_size)); - 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); - if (strchr (skeleton, '/')) - strcpy (full_skeleton, skeleton); - else - strcpy (full_skeleton + pkgdatadirlen + 1, skeleton); + char const *m4 = (m4 = getenv ("M4")) ? m4 : M4; + char const *datadir = pkgdatadir (); + char *m4sugar = xconcatenated_filename (datadir, "m4sugar/m4sugar.m4", NULL); + char *m4bison = xconcatenated_filename (datadir, "bison.m4", NULL); + char *skel = (IS_PATH_WITH_DIR (skeleton) + ? xstrdup (skeleton) + : xconcatenated_filename (datadir, skeleton, NULL)); /* 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")); + xfclose (xfopen (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, m4sugar, m4bison, skel); /* 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 @@ -612,6 +575,7 @@ output_skeleton (void) for details. */ { + char const *argv[10]; int i = 0; argv[i++] = m4; @@ -628,58 +592,55 @@ output_skeleton (void) argv[i++] = M4_GNU_OPTION; argv[i++] = "-I"; - argv[i++] = pkgdatadir; + argv[i++] = datadir; if (trace_flag & trace_m4) argv[i++] = "-dV"; - argv[i++] = full_m4sugar; + argv[i++] = m4sugar; argv[i++] = "-"; - argv[i++] = full_m4bison; - argv[i++] = full_skeleton; + argv[i++] = m4bison; + argv[i++] = skel; argv[i++] = NULL; aver (i <= ARRAY_CARDINALITY (argv)); + + /* The ugly cast is because gnulib gets the const-ness wrong. */ + pid = create_pipe_bidi ("m4", m4, (char **)(void*)argv, false, true, + true, filter_fd); } - init_subpipe (); - pid = create_subpipe (argv, filter_fd); - free (full_m4sugar); - free (full_m4bison); - free (full_skeleton); + free (m4sugar); + free (m4bison); + free (skel); if (trace_flag & trace_muscles) muscles_output (stderr); { - FILE *out = fdopen (filter_fd[0], "w"); - if (! out) - error (EXIT_FAILURE, get_errno (), - "fdopen"); + FILE *out = xfdopen (filter_fd[1], "w"); muscles_output (out); 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) - error (EXIT_FAILURE, get_errno (), - "fdopen"); - scan_skel (in); - xfclose (in); - reap_subpipe (pid, m4); + { + FILE *in = xfdopen (filter_fd[0], "r"); + scan_skel (in); + /* scan_skel should have read all of M4's output. Otherwise, when we + close the pipe, we risk letting M4 report a broken-pipe to the + Bison user. */ + aver (feof (in)); + xfclose (in); + } + wait_subprocess (pid, "m4", false, false, true, true, NULL); timevar_pop (TV_M4); } 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; + /* BISON_USE_PUSH_FOR_PULL is for the test suite and should not be + documented for the user. */ + char const *cp = getenv ("BISON_USE_PUSH_FOR_PULL"); + bool use_push_for_pull_flag = cp && *cp && strtol (cp, 0, 10); /* Flags. */ MUSCLE_INSERT_BOOL ("defines_flag", defines_flag); @@ -687,6 +648,7 @@ prepare (void) MUSCLE_INSERT_BOOL ("nondeterministic_flag", nondeterministic_parser); MUSCLE_INSERT_BOOL ("synclines_flag", !no_lines_flag); MUSCLE_INSERT_BOOL ("tag_seen_flag", tag_seen); + MUSCLE_INSERT_BOOL ("token_table_flag", token_table_flag); MUSCLE_INSERT_BOOL ("use_push_for_pull_flag", use_push_for_pull_flag); MUSCLE_INSERT_BOOL ("yacc_flag", yacc_flag); @@ -718,7 +680,7 @@ prepare (void) /* 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", compute_pkgdatadir ()); + MUSCLE_INSERT_STRING_RAW ("pkgdatadir", pkgdatadir ()); } } @@ -747,8 +709,8 @@ output (void) } char const * -compute_pkgdatadir (void) +pkgdatadir (void) { - char const *pkgdatadir = getenv ("BISON_PKGDATADIR"); - return pkgdatadir ? pkgdatadir : PKGDATADIR; + char const *cp = getenv ("BISON_PKGDATADIR"); + return cp ? cp : PKGDATADIR; }