- output_table_data (&output_obstack, table,
- table[0], 1, high + 1);
- macro_insert ("table", obstack_finish (&output_obstack));
- XFREE (table);
-}
-
-
-static void
-output_check (void)
-{
- output_table_data (&output_obstack, check,
- check[0], 1, high + 1);
- macro_insert ("check", obstack_finish (&output_obstack));
- XFREE (check);
-}
-
-/* compute and output yydefact, yydefgoto, yypact, yypgoto, yytable
- and yycheck. */
-
-static void
-output_actions (void)
-{
- nvectors = nstates + nvars;
-
- froms = XCALLOC (short *, nvectors);
- tos = XCALLOC (short *, nvectors);
- tally = XCALLOC (short, nvectors);
- width = XCALLOC (short, nvectors);
-
- token_actions ();
- free_shifts ();
- free_reductions ();
- XFREE (lookaheads);
- XFREE (LA);
- XFREE (LAruleno);
- XFREE (accessing_symbol);
-
- goto_actions ();
- XFREE (goto_map + ntokens);
- XFREE (from_state);
- XFREE (to_state);
-
- sort_actions ();
- pack_table ();
-
- output_base ();
- output_table ();
-
- output_check ();
-}
-
-/*------------------------------------------.
-| Copy the parser code into TABLE_OBSTACK. |
-`------------------------------------------*/
-
-static void
-output_parser (void)
-{
- int c;
- FILE *fskel;
- size_t line;
- int actions_dumped = 0;
-
- /* Loop over lines in the standard parser file. */
- if (!skeleton)
- {
- if (semantic_parser)
- skeleton = skeleton_find ("BISON_HAIRY", BISON_HAIRY);
- else
- skeleton = skeleton_find ("BISON_SIMPLE", BISON_SIMPLE);
- }
- fskel = xfopen (skeleton, "r");
-
- /* New output code. */
- line = 1;
- c = getc (fskel);
- while (c != EOF)
- {
- if (c != '%')
- {
- if (c == '\n')
- ++line;
- obstack_1grow (&table_obstack, c);
- c = getc (fskel);
- }
- else if ((c = getc (fskel)) == '%')
- {
- /* Read the macro. */
- const char* macro_key = 0;
- const char* macro_value = 0;
- while (isalnum (c = getc (fskel)) || c == '_')
- obstack_1grow (¯o_obstack, c);
- obstack_1grow (¯o_obstack, 0);
-
- /* Output the right value, or see if it's something special. */
- macro_key = obstack_finish (¯o_obstack);
- macro_value = macro_find (macro_key);
- if (macro_value)
- obstack_sgrow (&table_obstack, macro_value);
- else if (!strcmp (macro_key, "line"))
- obstack_fgrow1 (&table_obstack, "%d", line + 1);
- else if (!strcmp (macro_key, "action"))
- {
- size_t size = obstack_object_size (&action_obstack);
- obstack_grow (&table_obstack,
- obstack_finish (&action_obstack), size);
- }
- else
- {
- obstack_sgrow (&table_obstack, "%%");
- obstack_sgrow (&table_obstack, macro_key);
- }
- }
- else
- obstack_1grow (&table_obstack, '%');
- }
-
- /* End. */
- xfclose (fskel);
-}
-
-static void
-free_itemsets (void)
-{
- core *cp, *cptmp;
-
- XFREE (state_table);
-
- for (cp = first_state; cp; cp = cptmp)
- {
- cptmp = cp->next;
- XFREE (cp);
- }
-}
-
-/* FIXME. */
-
-#define MACRO_INSERT_INT(Key, Value) \
-{ \
- obstack_fgrow1 (¯o_obstack, "%d", Value); \
- obstack_1grow (¯o_obstack, 0); \
- macro_insert (Key, obstack_finish (¯o_obstack)); \
-}
-
-#define MACRO_INSERT_STRING(Key, Value) \
-{ \
- obstack_sgrow (¯o_obstack, Value); \
- obstack_1grow (¯o_obstack, 0); \
- macro_insert (Key, obstack_finish (¯o_obstack)); \
-}
-
-#define MACRO_INSERT_PREFIX(Key, Value) \
-{ \
- obstack_fgrow2 (¯o_obstack, "%s%s", spec_name_prefix, Value); \
- obstack_1grow (¯o_obstack, 0); \
- macro_insert (Key, obstack_finish (¯o_obstack)); \
+ FILE *in;
+ FILE *out;
+ int filter_fd[2];
+ char const *argv[9];
+ 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);
+
+ /* 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);
+
+ /* 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
+ <http://lists.gnu.org/archive/html/bug-bison/2008-07/msg00000.html>
+ 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
+ <http://lists.gnu.org/archive/html/bug-bison/2008-07/msg00000.html>
+ for details. */
+ unsetenv ("POSIXLY_CORRECT");
+ init_subpipe ();
+ pid = create_subpipe (argv, filter_fd);
+ 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_code_props_output (out, "destructors", &symbol_destructor_get);
+ symbol_code_props_output (out, "printers", &symbol_printer_get);
+
+ muscles_m4_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);
+ timevar_pop (TV_M4);