- int c;
- FILE *fskel;
- size_t line;
-
- fskel = xfopen (skel_filename, "r");
-
- /* New output code. */
- line = 1;
- c = getc (fskel);
- while (c != EOF)
- {
- if (c != '%')
- {
- if (c == '\n')
- ++line;
- obstack_1grow (oout, c);
- c = getc (fskel);
- }
- else if ((c = getc (fskel)) == '%')
- {
- /* Read the muscle. */
- const char *muscle_key = 0;
- const char *muscle_value = 0;
-
- while (isalnum (c = getc (fskel)) || c == '_')
- obstack_1grow (&muscle_obstack, c);
- obstack_1grow (&muscle_obstack, 0);
-
- /* Output the right value, or see if it's something special. */
- muscle_key = obstack_finish (&muscle_obstack);
- muscle_value = muscle_find (muscle_key);
- if (muscle_value)
- obstack_sgrow (oout, muscle_value);
- else if (!strcmp (muscle_key, "line"))
- obstack_fgrow1 (oout, "%d", line + 1);
- else if (!strcmp (muscle_key, "input_line"))
- obstack_fgrow1 (oout, "%d", lineno);
- else
- {
- obstack_sgrow (oout, "%%");
- obstack_sgrow (oout, muscle_key);
- }
- }
- else
- obstack_1grow (oout, '%');
- }
-
- /* End. */
- xfclose (fskel);
+ FILE *in;
+ FILE *out;
+ int filter_fd[2];
+ char const *argv[6];
+ 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. */
+ char const m4sugar[] = "m4sugar/m4sugar.m4";
+ char *full_m4sugar;
+ char *full_cm4;
+ char *full_skeleton;
+ char const *p;
+ char const *m4 = (p = getenv ("M4")) ? p : M4;
+ char const *pkgdatadir = (p = getenv ("BISON_PKGDATADIR")) ? p : 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));
+ strcpy (full_skeleton, pkgdatadir);
+ 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);
+ 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);
+
+ argv[0] = m4;
+ argv[1] = full_m4sugar;
+ argv[2] = "-";
+ argv[3] = full_cm4;
+ argv[4] = full_skeleton;
+ argv[5] = NULL;
+
+ init_subpipe ();
+ pid = create_subpipe (argv, filter_fd);
+ free (full_m4sugar);
+ free (full_cm4);
+ 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);
+
+ /* Read and process m4's output. */
+ timevar_push (TV_M4);
+ 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);