1 | /* Output the generated parsing program for Bison. |
2 | |
3 | Copyright (C) 1984, 1986, 1989, 1992, 2000-2015, 2018-2019 Free |
4 | Software Foundation, Inc. |
5 | |
6 | This file is part of Bison, the GNU Compiler Compiler. |
7 | |
8 | This program is free software: you can redistribute it and/or modify |
9 | it under the terms of the GNU General Public License as published by |
10 | the Free Software Foundation, either version 3 of the License, or |
11 | (at your option) any later version. |
12 | |
13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | GNU General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU General Public License |
19 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
20 | |
21 | #include <config.h> |
22 | #include "system.h" |
23 | |
24 | #include <filename.h> /* IS_PATH_WITH_DIR */ |
25 | #include <get-errno.h> |
26 | #include <path-join.h> |
27 | #include <quotearg.h> |
28 | #include <spawn-pipe.h> |
29 | #include <timevar.h> |
30 | #include <wait-process.h> |
31 | |
32 | #include "complain.h" |
33 | #include "files.h" |
34 | #include "getargs.h" |
35 | #include "gram.h" |
36 | #include "muscle-tab.h" |
37 | #include "output.h" |
38 | #include "reader.h" |
39 | #include "reduce.h" |
40 | #include "scan-code.h" /* max_left_semantic_context */ |
41 | #include "scan-skel.h" |
42 | #include "symtab.h" |
43 | #include "tables.h" |
44 | |
45 | static struct obstack format_obstack; |
46 | |
47 | |
48 | /*-------------------------------------------------------------------. |
49 | | Create a function NAME which associates to the muscle NAME the | |
50 | | result of formatting the FIRST and then TABLE_DATA[BEGIN..END[ (of | |
51 | | TYPE), and to the muscle NAME_max, the max value of the | |
52 | | TABLE_DATA. | |
53 | `-------------------------------------------------------------------*/ |
54 | |
55 | |
56 | #define GENERATE_MUSCLE_INSERT_TABLE(Name, Type) \ |
57 | \ |
58 | static void \ |
59 | Name (char const *name, Type *table_data, Type first, \ |
60 | int begin, int end) \ |
61 | { \ |
62 | Type min = first; \ |
63 | Type max = first; \ |
64 | int j = 1; \ |
65 | \ |
66 | obstack_printf (&format_obstack, "%6d", first); \ |
67 | for (int i = begin; i < end; ++i) \ |
68 | { \ |
69 | obstack_1grow (&format_obstack, ','); \ |
70 | if (j >= 10) \ |
71 | { \ |
72 | obstack_sgrow (&format_obstack, "\n "); \ |
73 | j = 1; \ |
74 | } \ |
75 | else \ |
76 | ++j; \ |
77 | obstack_printf (&format_obstack, "%6d", table_data[i]); \ |
78 | if (table_data[i] < min) \ |
79 | min = table_data[i]; \ |
80 | if (max < table_data[i]) \ |
81 | max = table_data[i]; \ |
82 | } \ |
83 | muscle_insert (name, obstack_finish0 (&format_obstack)); \ |
84 | \ |
85 | long lmin = min; \ |
86 | long lmax = max; \ |
87 | /* Build 'NAME_min' and 'NAME_max' in the obstack. */ \ |
88 | obstack_printf (&format_obstack, "%s_min", name); \ |
89 | MUSCLE_INSERT_LONG_INT (obstack_finish0 (&format_obstack), lmin); \ |
90 | obstack_printf (&format_obstack, "%s_max", name); \ |
91 | MUSCLE_INSERT_LONG_INT (obstack_finish0 (&format_obstack), lmax); \ |
92 | } |
93 | |
94 | GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_unsigned_table, unsigned) |
95 | GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_int_table, int) |
96 | GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_base_table, base_number) |
97 | GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_rule_number_table, rule_number) |
98 | GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_symbol_number_table, symbol_number) |
99 | GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_item_number_table, item_number) |
100 | GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_state_number_table, state_number) |
101 | |
102 | /*----------------------------------------------------------------. |
103 | | Print to OUT a representation of CP quoted and escaped for M4. | |
104 | `----------------------------------------------------------------*/ |
105 | |
106 | static void |
107 | quoted_output (FILE *out, char const *cp) |
108 | { |
109 | fprintf (out, "[[" ); |
110 | |
111 | for (; *cp; cp++) |
112 | switch (*cp) |
113 | { |
114 | case '$': fputs ("$][" , out); break; |
115 | case '@': fputs ("@@" , out); break; |
116 | case '[': fputs ("@{" , out); break; |
117 | case ']': fputs ("@}" , out); break; |
118 | default: fputc (*cp, out); break; |
119 | } |
120 | |
121 | fprintf (out, "]]" ); |
122 | } |
123 | |
124 | /*----------------------------------------------------------------. |
125 | | Print to OUT a representation of STRING quoted and escaped both | |
126 | | for C and M4. | |
127 | `----------------------------------------------------------------*/ |
128 | |
129 | static void |
130 | string_output (FILE *out, char const *string) |
131 | { |
132 | quoted_output (out, quotearg_style (c_quoting_style, string)); |
133 | } |
134 | |
135 | |
136 | /* Generate the b4_<MUSCLE_NAME> (e.g., b4_tname) table with the |
137 | symbol names (aka tags). */ |
138 | |
139 | static void |
140 | prepare_symbol_names (char const *muscle_name) |
141 | { |
142 | /* We assume that the table will be output starting at column 2. */ |
143 | int j = 2; |
144 | struct quoting_options *qo = clone_quoting_options (0); |
145 | set_quoting_style (qo, c_quoting_style); |
146 | set_quoting_flags (qo, QA_SPLIT_TRIGRAPHS); |
147 | for (int i = 0; i < nsyms; i++) |
148 | { |
149 | char *cp = quotearg_alloc (symbols[i]->tag, -1, qo); |
150 | /* Width of the next token, including the two quotes, the |
151 | comma and the space. */ |
152 | int width = strlen (cp) + 2; |
153 | |
154 | if (j + width > 75) |
155 | { |
156 | obstack_sgrow (&format_obstack, "\n " ); |
157 | j = 1; |
158 | } |
159 | |
160 | if (i) |
161 | obstack_1grow (&format_obstack, ' '); |
162 | obstack_escape (&format_obstack, cp); |
163 | free (cp); |
164 | obstack_1grow (&format_obstack, ','); |
165 | j += width; |
166 | } |
167 | free (qo); |
168 | obstack_sgrow (&format_obstack, " ]b4_null[" ); |
169 | |
170 | /* Finish table and store. */ |
171 | muscle_insert (muscle_name, obstack_finish0 (&format_obstack)); |
172 | } |
173 | |
174 | |
175 | /*------------------------------------------------------------------. |
176 | | Prepare the muscles related to the symbols: translate, tname, and | |
177 | | toknum. | |
178 | `------------------------------------------------------------------*/ |
179 | |
180 | static void |
181 | prepare_symbols (void) |
182 | { |
183 | MUSCLE_INSERT_INT ("tokens_number" , ntokens); |
184 | MUSCLE_INSERT_INT ("nterms_number" , nvars); |
185 | MUSCLE_INSERT_INT ("symbols_number" , nsyms); |
186 | MUSCLE_INSERT_INT ("undef_token_number" , undeftoken->content->number); |
187 | MUSCLE_INSERT_INT ("user_token_number_max" , max_user_token_number); |
188 | |
189 | muscle_insert_symbol_number_table ("translate" , |
190 | token_translations, |
191 | token_translations[0], |
192 | 1, max_user_token_number + 1); |
193 | |
194 | /* tname -- token names. */ |
195 | prepare_symbol_names ("tname" ); |
196 | |
197 | /* Output YYTOKNUM. */ |
198 | { |
199 | int *values = xnmalloc (ntokens, sizeof *values); |
200 | for (int i = 0; i < ntokens; ++i) |
201 | values[i] = symbols[i]->content->user_token_number; |
202 | muscle_insert_int_table ("toknum" , values, |
203 | values[0], 1, ntokens); |
204 | free (values); |
205 | } |
206 | } |
207 | |
208 | |
209 | /*-------------------------------------------------------------. |
210 | | Prepare the muscles related to the rules: rhs, prhs, r1, r2, | |
211 | | rline, dprec, merger, immediate. | |
212 | `-------------------------------------------------------------*/ |
213 | |
214 | static void |
215 | prepare_rules (void) |
216 | { |
217 | unsigned *prhs = xnmalloc (nrules, sizeof *prhs); |
218 | item_number *rhs = xnmalloc (nritems, sizeof *rhs); |
219 | unsigned *rline = xnmalloc (nrules, sizeof *rline); |
220 | symbol_number *r1 = xnmalloc (nrules, sizeof *r1); |
221 | unsigned *r2 = xnmalloc (nrules, sizeof *r2); |
222 | int *dprec = xnmalloc (nrules, sizeof *dprec); |
223 | int *merger = xnmalloc (nrules, sizeof *merger); |
224 | int *immediate = xnmalloc (nrules, sizeof *immediate); |
225 | |
226 | /* Index in RHS. */ |
227 | unsigned i = 0; |
228 | for (rule_number r = 0; r < nrules; ++r) |
229 | { |
230 | /* Index of rule R in RHS. */ |
231 | prhs[r] = i; |
232 | /* RHS of the rule R. */ |
233 | for (item_number *rhsp = rules[r].rhs; 0 <= *rhsp; ++rhsp) |
234 | rhs[i++] = *rhsp; |
235 | /* Separator in RHS. */ |
236 | rhs[i++] = -1; |
237 | |
238 | /* Line where rule was defined. */ |
239 | rline[r] = rules[r].location.start.line; |
240 | /* LHS of the rule R. */ |
241 | r1[r] = rules[r].lhs->number; |
242 | /* Length of rule R's RHS. */ |
243 | r2[r] = rule_rhs_length (&rules[r]); |
244 | /* Dynamic precedence (GLR). */ |
245 | dprec[r] = rules[r].dprec; |
246 | /* Merger-function index (GLR). */ |
247 | merger[r] = rules[r].merger; |
248 | /* Immediate reduction flags (GLR). */ |
249 | immediate[r] = rules[r].is_predicate; |
250 | } |
251 | aver (i == nritems); |
252 | |
253 | muscle_insert_item_number_table ("rhs" , rhs, ritem[0], 1, nritems); |
254 | muscle_insert_unsigned_table ("prhs" , prhs, 0, 0, nrules); |
255 | muscle_insert_unsigned_table ("rline" , rline, 0, 0, nrules); |
256 | muscle_insert_symbol_number_table ("r1" , r1, 0, 0, nrules); |
257 | muscle_insert_unsigned_table ("r2" , r2, 0, 0, nrules); |
258 | muscle_insert_int_table ("dprec" , dprec, 0, 0, nrules); |
259 | muscle_insert_int_table ("merger" , merger, 0, 0, nrules); |
260 | muscle_insert_int_table ("immediate" , immediate, 0, 0, nrules); |
261 | |
262 | MUSCLE_INSERT_INT ("rules_number" , nrules); |
263 | MUSCLE_INSERT_INT ("max_left_semantic_context" , max_left_semantic_context); |
264 | |
265 | free (prhs); |
266 | free (rhs); |
267 | free (rline); |
268 | free (r1); |
269 | free (r2); |
270 | free (dprec); |
271 | free (merger); |
272 | free (immediate); |
273 | } |
274 | |
275 | /*--------------------------------------------. |
276 | | Prepare the muscles related to the states. | |
277 | `--------------------------------------------*/ |
278 | |
279 | static void |
280 | prepare_states (void) |
281 | { |
282 | symbol_number *values = xnmalloc (nstates, sizeof *values); |
283 | for (state_number i = 0; i < nstates; ++i) |
284 | values[i] = states[i]->accessing_symbol; |
285 | muscle_insert_symbol_number_table ("stos" , values, |
286 | 0, 1, nstates); |
287 | free (values); |
288 | |
289 | MUSCLE_INSERT_INT ("last" , high); |
290 | MUSCLE_INSERT_INT ("final_state_number" , final_state->number); |
291 | MUSCLE_INSERT_INT ("states_number" , nstates); |
292 | } |
293 | |
294 | |
295 | /*-------------------------------------------------------. |
296 | | Compare two symbols by type-name, and then by number. | |
297 | `-------------------------------------------------------*/ |
298 | |
299 | static int |
300 | symbol_type_name_cmp (const symbol **lhs, const symbol **rhs) |
301 | { |
302 | int res = uniqstr_cmp ((*lhs)->content->type_name, (*rhs)->content->type_name); |
303 | if (!res) |
304 | res = (*lhs)->content->number - (*rhs)->content->number; |
305 | return res; |
306 | } |
307 | |
308 | |
309 | /*----------------------------------------------------------------. |
310 | | Return a (malloc'ed) table of the symbols sorted by type-name. | |
311 | `----------------------------------------------------------------*/ |
312 | |
313 | static symbol ** |
314 | symbols_by_type_name (void) |
315 | { |
316 | typedef int (*qcmp_type) (const void *, const void *); |
317 | symbol **res = xmemdup (symbols, nsyms * sizeof *res); |
318 | qsort (res, nsyms, sizeof *res, (qcmp_type) &symbol_type_name_cmp); |
319 | return res; |
320 | } |
321 | |
322 | |
323 | /*------------------------------------------------------------------. |
324 | | Define b4_type_names, which is a list of (lists of the numbers of | |
325 | | symbols with same type-name). | |
326 | `------------------------------------------------------------------*/ |
327 | |
328 | static void |
329 | type_names_output (FILE *out) |
330 | { |
331 | symbol **syms = symbols_by_type_name (); |
332 | fputs ("m4_define([b4_type_names],\n[" , out); |
333 | for (int i = 0; i < nsyms; /* nothing */) |
334 | { |
335 | /* The index of the first symbol of the current type-name. */ |
336 | int i0 = i; |
337 | fputs (i ? ",\n[" : "[" , out); |
338 | for (; i < nsyms |
339 | && syms[i]->content->type_name == syms[i0]->content->type_name; ++i) |
340 | fprintf (out, "%s%d" , i != i0 ? ", " : "" , syms[i]->content->number); |
341 | fputs ("]" , out); |
342 | } |
343 | fputs ("])\n\n" , out); |
344 | free (syms); |
345 | } |
346 | |
347 | |
348 | /*-------------------------------------. |
349 | | The list of all the symbol numbers. | |
350 | `-------------------------------------*/ |
351 | |
352 | static void |
353 | symbol_numbers_output (FILE *out) |
354 | { |
355 | fputs ("m4_define([b4_symbol_numbers],\n[" , out); |
356 | for (int i = 0; i < nsyms; ++i) |
357 | fprintf (out, "%s[%d]" , i ? ", " : "" , i); |
358 | fputs ("])\n\n" , out); |
359 | } |
360 | |
361 | |
362 | /*---------------------------------. |
363 | | Output the user actions to OUT. | |
364 | `---------------------------------*/ |
365 | |
366 | static void |
367 | user_actions_output (FILE *out) |
368 | { |
369 | fputs ("m4_define([b4_actions], \n[" , out); |
370 | for (rule_number r = 0; r < nrules; ++r) |
371 | if (rules[r].action) |
372 | { |
373 | fprintf (out, "%s(%d, [b4_syncline(%d, " , |
374 | rules[r].is_predicate ? "b4_predicate_case" : "b4_case" , |
375 | r + 1, rules[r].action_loc.start.line); |
376 | string_output (out, rules[r].action_loc.start.file); |
377 | fprintf (out, ")dnl\n[ %s]])\n\n" , rules[r].action); |
378 | } |
379 | fputs ("])\n\n" , out); |
380 | } |
381 | |
382 | /*------------------------------------. |
383 | | Output the merge functions to OUT. | |
384 | `------------------------------------*/ |
385 | |
386 | static void |
387 | merger_output (FILE *out) |
388 | { |
389 | fputs ("m4_define([b4_mergers], \n[[" , out); |
390 | int n; |
391 | merger_list* p; |
392 | for (n = 1, p = merge_functions; p != NULL; n += 1, p = p->next) |
393 | { |
394 | if (p->type[0] == '\0') |
395 | fprintf (out, " case %d: *yy0 = %s (*yy0, *yy1); break;\n" , |
396 | n, p->name); |
397 | else |
398 | fprintf (out, " case %d: yy0->%s = %s (*yy0, *yy1); break;\n" , |
399 | n, p->type, p->name); |
400 | } |
401 | fputs ("]])\n\n" , out); |
402 | } |
403 | |
404 | |
405 | /*---------------------------------------------. |
406 | | Prepare the muscles for symbol definitions. | |
407 | `---------------------------------------------*/ |
408 | |
409 | static void |
410 | prepare_symbol_definitions (void) |
411 | { |
412 | /* Map "orig NUM" to new numbers. See data/README. */ |
413 | for (symbol_number i = ntokens; i < nsyms + nuseless_nonterminals; ++i) |
414 | { |
415 | obstack_printf (&format_obstack, "symbol(orig %d, number)" , i); |
416 | const char *key = obstack_finish0 (&format_obstack); |
417 | MUSCLE_INSERT_INT (key, nterm_map ? nterm_map[i - ntokens] : i); |
418 | } |
419 | |
420 | for (int i = 0; i < nsyms; ++i) |
421 | { |
422 | symbol *sym = symbols[i]; |
423 | const char *key; |
424 | |
425 | #define SET_KEY(Entry) \ |
426 | obstack_printf (&format_obstack, "symbol(%d, %s)", \ |
427 | i, Entry); \ |
428 | key = obstack_finish0 (&format_obstack); |
429 | |
430 | #define SET_KEY2(Entry, Suffix) \ |
431 | obstack_printf (&format_obstack, "symbol(%d, %s_%s)", \ |
432 | i, Entry, Suffix); \ |
433 | key = obstack_finish0 (&format_obstack); |
434 | |
435 | /* Whether the symbol has an identifier. */ |
436 | const char *id = symbol_id_get (sym); |
437 | SET_KEY ("has_id" ); |
438 | MUSCLE_INSERT_INT (key, !!id); |
439 | |
440 | /* Its identifier. */ |
441 | SET_KEY ("id" ); |
442 | MUSCLE_INSERT_STRING (key, id ? id : "" ); |
443 | |
444 | /* Its tag. Typically for documentation purpose. */ |
445 | SET_KEY ("tag" ); |
446 | MUSCLE_INSERT_STRING (key, sym->tag); |
447 | |
448 | SET_KEY ("user_number" ); |
449 | MUSCLE_INSERT_INT (key, sym->content->user_token_number); |
450 | |
451 | SET_KEY ("is_token" ); |
452 | MUSCLE_INSERT_INT (key, |
453 | i < ntokens && sym != errtoken && sym != undeftoken); |
454 | |
455 | SET_KEY ("number" ); |
456 | MUSCLE_INSERT_INT (key, sym->content->number); |
457 | |
458 | SET_KEY ("has_type" ); |
459 | MUSCLE_INSERT_INT (key, !!sym->content->type_name); |
460 | |
461 | SET_KEY ("type" ); |
462 | MUSCLE_INSERT_STRING (key, sym->content->type_name |
463 | ? sym->content->type_name : "" ); |
464 | |
465 | for (int j = 0; j < CODE_PROPS_SIZE; ++j) |
466 | { |
467 | /* "printer", not "%printer". */ |
468 | char const *pname = code_props_type_string (j) + 1; |
469 | code_props const *p = symbol_code_props_get (sym, j); |
470 | SET_KEY2 ("has" , pname); |
471 | MUSCLE_INSERT_INT (key, !!p->code); |
472 | |
473 | if (p->code) |
474 | { |
475 | SET_KEY2 (pname, "file" ); |
476 | MUSCLE_INSERT_C_STRING (key, p->location.start.file); |
477 | |
478 | SET_KEY2 (pname, "line" ); |
479 | MUSCLE_INSERT_INT (key, p->location.start.line); |
480 | |
481 | SET_KEY2 (pname, "loc" ); |
482 | muscle_location_grow (key, p->location); |
483 | |
484 | SET_KEY (pname); |
485 | MUSCLE_INSERT_STRING_RAW (key, p->code); |
486 | } |
487 | } |
488 | #undef SET_KEY2 |
489 | #undef SET_KEY |
490 | } |
491 | } |
492 | |
493 | |
494 | static void |
495 | prepare_actions (void) |
496 | { |
497 | /* Figure out the actions for the specified state, indexed by |
498 | lookahead token type. */ |
499 | |
500 | muscle_insert_rule_number_table ("defact" , yydefact, |
501 | yydefact[0], 1, nstates); |
502 | |
503 | /* Figure out what to do after reducing with each rule, depending on |
504 | the saved state from before the beginning of parsing the data |
505 | that matched this rule. */ |
506 | muscle_insert_state_number_table ("defgoto" , yydefgoto, |
507 | yydefgoto[0], 1, nsyms - ntokens); |
508 | |
509 | |
510 | /* Output PACT. */ |
511 | muscle_insert_base_table ("pact" , base, |
512 | base[0], 1, nstates); |
513 | MUSCLE_INSERT_INT ("pact_ninf" , base_ninf); |
514 | |
515 | /* Output PGOTO. */ |
516 | muscle_insert_base_table ("pgoto" , base, |
517 | base[nstates], nstates + 1, nvectors); |
518 | |
519 | muscle_insert_base_table ("table" , table, |
520 | table[0], 1, high + 1); |
521 | MUSCLE_INSERT_INT ("table_ninf" , table_ninf); |
522 | |
523 | muscle_insert_base_table ("check" , check, |
524 | check[0], 1, high + 1); |
525 | |
526 | /* GLR parsing slightly modifies YYTABLE and YYCHECK (and thus |
527 | YYPACT) so that in states with unresolved conflicts, the default |
528 | reduction is not used in the conflicted entries, so that there is |
529 | a place to put a conflict pointer. |
530 | |
531 | This means that YYCONFLP and YYCONFL are nonsense for a non-GLR |
532 | parser, so we could avoid accidents by not writing them out in |
533 | that case. Nevertheless, it seems even better to be able to use |
534 | the GLR skeletons even without the non-deterministic tables. */ |
535 | muscle_insert_unsigned_table ("conflict_list_heads" , conflict_table, |
536 | conflict_table[0], 1, high + 1); |
537 | muscle_insert_unsigned_table ("conflicting_rules" , conflict_list, |
538 | 0, 1, conflict_list_cnt); |
539 | } |
540 | |
541 | |
542 | /*--------------------------------------------. |
543 | | Output the definitions of all the muscles. | |
544 | `--------------------------------------------*/ |
545 | |
546 | static void |
547 | muscles_output (FILE *out) |
548 | { |
549 | fputs ("m4_init()\n" , out); |
550 | merger_output (out); |
551 | symbol_numbers_output (out); |
552 | type_names_output (out); |
553 | user_actions_output (out); |
554 | /* Must be last. */ |
555 | muscles_m4_output (out); |
556 | } |
557 | |
558 | /*---------------------------. |
559 | | Call the skeleton parser. | |
560 | `---------------------------*/ |
561 | |
562 | static void |
563 | output_skeleton (void) |
564 | { |
565 | /* Compute the names of the package data dir and skeleton files. */ |
566 | char const *m4 = (m4 = getenv ("M4" )) ? m4 : M4; |
567 | char const *datadir = pkgdatadir (); |
568 | char *skeldir = xpath_join (datadir, "skeletons" ); |
569 | char *m4sugar = xpath_join (datadir, "m4sugar/m4sugar.m4" ); |
570 | char *m4bison = xpath_join (skeldir, "bison.m4" ); |
571 | char *skel = (IS_PATH_WITH_DIR (skeleton) |
572 | ? xstrdup (skeleton) |
573 | : xpath_join (skeldir, skeleton)); |
574 | |
575 | /* Test whether m4sugar.m4 is readable, to check for proper |
576 | installation. A faulty installation can cause deadlock, so a |
577 | cheap sanity check is worthwhile. */ |
578 | xfclose (xfopen (m4sugar, "r" )); |
579 | |
580 | /* Create an m4 subprocess connected to us via two pipes. */ |
581 | |
582 | if (trace_flag & trace_tools) |
583 | fprintf (stderr, "running: %s %s - %s %s\n" , |
584 | m4, m4sugar, m4bison, skel); |
585 | |
586 | /* Some future version of GNU M4 (most likely 1.6) may treat the -dV in a |
587 | position-dependent manner. Keep it as the first argument so that all |
588 | files are traced. |
589 | |
590 | See the thread starting at |
591 | <http://lists.gnu.org/archive/html/bug-bison/2008-07/msg00000.html> |
592 | for details. */ |
593 | int filter_fd[2]; |
594 | pid_t pid; |
595 | { |
596 | char const *argv[10]; |
597 | int i = 0; |
598 | argv[i++] = m4; |
599 | |
600 | /* When POSIXLY_CORRECT is set, GNU M4 1.6 and later disable GNU |
601 | extensions, which Bison's skeletons depend on. With older M4, |
602 | it has no effect. M4 1.4.12 added a -g/--gnu command-line |
603 | option to make it explicit that a program wants GNU M4 |
604 | extensions even when POSIXLY_CORRECT is set. |
605 | |
606 | See the thread starting at |
607 | <http://lists.gnu.org/archive/html/bug-bison/2008-07/msg00000.html> |
608 | for details. */ |
609 | if (*M4_GNU_OPTION) |
610 | argv[i++] = M4_GNU_OPTION; |
611 | |
612 | argv[i++] = "-I" ; |
613 | argv[i++] = datadir; |
614 | if (trace_flag & trace_m4) |
615 | argv[i++] = "-dV" ; |
616 | argv[i++] = m4sugar; |
617 | argv[i++] = "-" ; |
618 | argv[i++] = m4bison; |
619 | argv[i++] = skel; |
620 | argv[i++] = NULL; |
621 | aver (i <= ARRAY_CARDINALITY (argv)); |
622 | |
623 | /* The ugly cast is because gnulib gets the const-ness wrong. */ |
624 | pid = create_pipe_bidi ("m4" , m4, (char **)(void*)argv, false, true, |
625 | true, filter_fd); |
626 | } |
627 | |
628 | free (skeldir); |
629 | free (m4sugar); |
630 | free (m4bison); |
631 | free (skel); |
632 | |
633 | if (trace_flag & trace_muscles) |
634 | muscles_output (stderr); |
635 | { |
636 | FILE *out = xfdopen (filter_fd[1], "w" ); |
637 | muscles_output (out); |
638 | xfclose (out); |
639 | } |
640 | |
641 | /* Read and process m4's output. */ |
642 | timevar_push (tv_m4); |
643 | { |
644 | FILE *in = xfdopen (filter_fd[0], "r" ); |
645 | scan_skel (in); |
646 | /* scan_skel should have read all of M4's output. Otherwise, when we |
647 | close the pipe, we risk letting M4 report a broken-pipe to the |
648 | Bison user. */ |
649 | aver (feof (in)); |
650 | xfclose (in); |
651 | } |
652 | wait_subprocess (pid, "m4" , false, false, true, true, NULL); |
653 | timevar_pop (tv_m4); |
654 | } |
655 | |
656 | static void |
657 | prepare (void) |
658 | { |
659 | /* BISON_USE_PUSH_FOR_PULL is for the test suite and should not be |
660 | documented for the user. */ |
661 | char const *cp = getenv ("BISON_USE_PUSH_FOR_PULL" ); |
662 | bool use_push_for_pull_flag = cp && *cp && strtol (cp, 0, 10); |
663 | |
664 | MUSCLE_INSERT_INT ("required_version" , required_version); |
665 | |
666 | /* Flags. */ |
667 | MUSCLE_INSERT_BOOL ("defines_flag" , defines_flag); |
668 | MUSCLE_INSERT_BOOL ("glr_flag" , glr_parser); |
669 | MUSCLE_INSERT_BOOL ("nondeterministic_flag" , nondeterministic_parser); |
670 | MUSCLE_INSERT_BOOL ("synclines_flag" , !no_lines_flag); |
671 | MUSCLE_INSERT_BOOL ("tag_seen_flag" , tag_seen); |
672 | MUSCLE_INSERT_BOOL ("token_table_flag" , token_table_flag); |
673 | MUSCLE_INSERT_BOOL ("use_push_for_pull_flag" , use_push_for_pull_flag); |
674 | MUSCLE_INSERT_BOOL ("yacc_flag" , !location_empty (yacc_loc)); |
675 | |
676 | /* File names. */ |
677 | if (spec_name_prefix) |
678 | MUSCLE_INSERT_STRING ("prefix" , spec_name_prefix); |
679 | |
680 | MUSCLE_INSERT_STRING ("file_name_all_but_ext" , all_but_ext); |
681 | |
682 | #define DEFINE(Name) MUSCLE_INSERT_STRING (#Name, Name ? Name : "") |
683 | DEFINE (dir_prefix); |
684 | DEFINE (parser_file_name); |
685 | DEFINE (spec_header_file); |
686 | DEFINE (spec_file_prefix); |
687 | DEFINE (spec_graph_file); |
688 | DEFINE (spec_name_prefix); |
689 | DEFINE (spec_outfile); |
690 | DEFINE (spec_verbose_file); |
691 | #undef DEFINE |
692 | |
693 | /* Find the right skeleton file, and add muscles about the skeletons. */ |
694 | if (skeleton) |
695 | MUSCLE_INSERT_C_STRING ("skeleton" , skeleton); |
696 | else |
697 | skeleton = language->skeleton; |
698 | |
699 | /* About the skeletons. */ |
700 | { |
701 | /* b4_skeletonsdir is used inside m4_include in the skeletons, so digraphs |
702 | would never be expanded. Hopefully no one has M4-special characters in |
703 | his Bison installation path. */ |
704 | char *skeldir = xpath_join (pkgdatadir (), "skeletons" ); |
705 | MUSCLE_INSERT_STRING_RAW ("skeletonsdir" , skeldir); |
706 | free (skeldir); |
707 | } |
708 | } |
709 | |
710 | |
711 | /*----------------------------------------------------------. |
712 | | Output the parsing tables and the parser code to ftable. | |
713 | `----------------------------------------------------------*/ |
714 | |
715 | void |
716 | output (void) |
717 | { |
718 | obstack_init (&format_obstack); |
719 | |
720 | prepare_symbols (); |
721 | prepare_rules (); |
722 | prepare_states (); |
723 | prepare_actions (); |
724 | prepare_symbol_definitions (); |
725 | |
726 | prepare (); |
727 | |
728 | /* Process the selected skeleton file. */ |
729 | output_skeleton (); |
730 | |
731 | /* If late errors were generated, destroy the generated source |
732 | files. */ |
733 | if (complaint_status) |
734 | unlink_generated_sources (); |
735 | |
736 | obstack_free (&format_obstack, NULL); |
737 | } |
738 | |