+ FILE *in;
+ FILE *out;
+ int filter_fd[2];
+ char const *argv[7];
+ 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 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);
+ 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);
+
+ 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;
+
+ init_subpipe ();
+ pid = create_subpipe (argv, filter_fd);
+ free (full_m4bison);
+ free (full_m4sugar);
+ 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);