]> git.saurik.com Git - bison.git/blob - src/output.c
* src/output.c (output_gram): Keep track of the hairy one.
[bison.git] / src / output.c
1 /* Output the generated parsing program for bison,
2 Copyright 1984, 1986, 1989, 1992, 2000, 2001 Free Software Foundation, Inc.
3
4 This file is part of Bison, the GNU Compiler Compiler.
5
6 Bison is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 Bison is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Bison; see the file COPYING. If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
20
21
22 /* The parser tables consist of these tables.
23 Starred ones needed only for the semantic parser.
24 Double starred are output only if switches are set.
25
26 yytranslate = vector mapping yylex's token numbers into bison's token
27 numbers.
28
29 ** yytname = vector of string-names indexed by bison token number
30
31 ** yytoknum = vector of yylex token numbers corresponding to entries
32 in yytname
33
34 yyrline = vector of line-numbers of all rules. For yydebug printouts.
35
36 yyrhs = vector of items of all rules.
37 This is exactly what ritems contains. For yydebug and for semantic
38 parser.
39
40 yyprhs[r] = index in yyrhs of first item for rule r.
41
42 yyr1[r] = symbol number of symbol that rule r derives.
43
44 yyr2[r] = number of symbols composing right hand side of rule r.
45
46 * yystos[s] = the symbol number of the symbol that leads to state s.
47
48 yydefact[s] = default rule to reduce with in state s,
49 when yytable doesn't specify something else to do.
50 Zero means the default is an error.
51
52 yydefgoto[i] = default state to go to after a reduction of a rule that
53 generates variable ntokens + i, except when yytable
54 specifies something else to do.
55
56 yypact[s] = index in yytable of the portion describing state s.
57 The lookahead token's type is used to index that portion
58 to find out what to do.
59
60 If the value in yytable is positive,
61 we shift the token and go to that state.
62
63 If the value is negative, it is minus a rule number to reduce by.
64
65 If the value is zero, the default action from yydefact[s] is used.
66
67 yypgoto[i] = the index in yytable of the portion describing
68 what to do after reducing a rule that derives variable i + ntokens.
69 This portion is indexed by the parser state number, s,
70 as of before the text for this nonterminal was read.
71 The value from yytable is the state to go to if
72 the corresponding value in yycheck is s.
73
74 yytable = a vector filled with portions for different uses,
75 found via yypact and yypgoto.
76
77 yycheck = a vector indexed in parallel with yytable.
78 It indicates, in a roundabout way, the bounds of the
79 portion you are trying to examine.
80
81 Suppose that the portion of yytable starts at index p
82 and the index to be examined within the portion is i.
83 Then if yycheck[p+i] != i, i is outside the bounds
84 of what is actually allocated, and the default
85 (from yydefact or yydefgoto) should be used.
86 Otherwise, yytable[p+i] should be used.
87
88 YYFINAL = the state number of the termination state.
89 YYFLAG = most negative short int. Used to flag ??
90 YYNTBASE = ntokens.
91 */
92
93 #include "system.h"
94 #include "quotearg.h"
95 #include "getargs.h"
96 #include "files.h"
97 #include "gram.h"
98 #include "LR0.h"
99 #include "complain.h"
100 #include "output.h"
101 #include "lalr.h"
102 #include "reader.h"
103 #include "conflicts.h"
104 #include "muscle_tab.h"
105
106
107 static int nvectors;
108 static int nentries;
109 static short **froms = NULL;
110 static short **tos = NULL;
111 static short *tally = NULL;
112 static short *width = NULL;
113 static short *actrow = NULL;
114 static short *state_count = NULL;
115 static short *order = NULL;
116 static short *base = NULL;
117 static short *pos = NULL;
118 static short *table = NULL;
119 static short *check = NULL;
120 static int lowzero;
121 static int high;
122
123 struct obstack muscle_obstack;
124 struct obstack output_obstack;
125
126 int error_verbose = 0;
127
128 /* FIXME. */
129
130 static inline void
131 output_table_data (struct obstack *oout,
132 short *table_data,
133 short first,
134 short begin,
135 short end)
136 {
137 int i;
138 int j = 1;
139
140 obstack_fgrow1 (oout, "%6d", first);
141 for (i = begin; i < end; ++i)
142 {
143 obstack_1grow (oout, ',');
144 if (j >= 10)
145 {
146 obstack_sgrow (oout, "\n ");
147 j = 1;
148 }
149 else
150 ++j;
151 obstack_fgrow1 (oout, "%6d", table_data[i]);
152 }
153 obstack_1grow (oout, 0);
154 }
155
156
157 static void
158 output_token_translations (void)
159 {
160 output_table_data (&output_obstack, token_translations,
161 0, 1, max_user_token_number + 1);
162 muscle_insert ("translate", obstack_finish (&output_obstack));
163 XFREE (token_translations);
164 }
165
166
167 static void
168 output_gram (void)
169 {
170 {
171 int i;
172 short *values = XCALLOC (short, nrules + 1);
173 for (i = 0; i < nrules + 1; ++i)
174 values[i] = rule_table[i].rhs;
175 output_table_data (&output_obstack, values,
176 0, 1, nrules + 1);
177 XFREE (values);
178 }
179
180 muscle_insert ("prhs", obstack_finish (&output_obstack));
181
182 {
183 size_t yyrhs_size = 1;
184 short *yyrhs, *sp;
185 int i;
186
187 for (sp = ritem + 1; *sp; sp++)
188 ++yyrhs_size;
189 yyrhs = XMALLOC (short, yyrhs_size);
190
191 for (sp = ritem + 1, i = 1; *sp; ++sp, ++i)
192 yyrhs[i] = *sp > 0 ? *sp : 0;
193
194 output_table_data (&output_obstack, yyrhs,
195 ritem[0], 1, yyrhs_size);
196 muscle_insert ("rhs", obstack_finish (&output_obstack));
197
198 XFREE (yyrhs);
199 }
200
201 #if 0
202 if (!semantic_parser)
203 obstack_sgrow (&table_obstack, "\n#endif\n");
204 #endif
205 }
206
207
208 static void
209 output_stos (void)
210 {
211 int i;
212 short *values = (short *) alloca (sizeof (short) * nstates);
213 for (i = 0; i < nstates; ++i)
214 values[i] = state_table[i]->accessing_symbol;
215 output_table_data (&output_obstack, values,
216 0, 1, nstates);
217 muscle_insert ("stos", obstack_finish (&output_obstack));
218 }
219
220
221 static void
222 output_rule_data (void)
223 {
224 int i;
225 int j;
226 short *short_tab = NULL;
227
228 {
229 short *values = XCALLOC (short, nrules + 1);
230 for (i = 0; i < nrules + 1; ++i)
231 values[i] = rule_table[i].line;
232 output_table_data (&output_obstack, values,
233 0, 1, nrules + 1);
234 muscle_insert ("rline", obstack_finish (&output_obstack));
235 XFREE (values);
236 }
237
238
239 j = 0;
240 for (i = 0; i < nsyms; i++)
241 {
242 /* Be sure not to use twice the same quotearg slot. */
243 const char *cp =
244 quotearg_n_style (1, c_quoting_style,
245 quotearg_style (escape_quoting_style, tags[i]));
246 /* Width of the next token, including the two quotes, the coma
247 and the space. */
248 int strsize = strlen (cp) + 2;
249
250 if (j + strsize > 75)
251 {
252 obstack_sgrow (&output_obstack, "\n ");
253 j = 2;
254 }
255
256 obstack_sgrow (&output_obstack, cp);
257 obstack_sgrow (&output_obstack, ", ");
258 j += strsize;
259 }
260 /* add a NULL entry to list of tokens */
261 obstack_sgrow (&output_obstack, "NULL");
262
263 /* Finish table and store. */
264 obstack_1grow (&output_obstack, 0);
265 muscle_insert ("tname", obstack_finish (&output_obstack));
266
267 /* Output YYTOKNUM. */
268 output_table_data (&output_obstack, user_toknums,
269 0, 1, ntokens + 1);
270 muscle_insert ("toknum", obstack_finish (&output_obstack));
271
272 /* Output YYR1. */
273 {
274 short *values = XCALLOC (short, nrules + 1);
275 for (i = 0; i < nrules + 1; ++i)
276 values[i] = rule_table[i].lhs;
277 output_table_data (&output_obstack, values,
278 0, 1, nrules + 1);
279 muscle_insert ("r1", obstack_finish (&output_obstack));
280 XFREE (values);
281 }
282
283 /* Output YYR2. */
284 short_tab = XMALLOC (short, nrules + 1);
285 for (i = 1; i < nrules; i++)
286 short_tab[i] = rule_table[i + 1].rhs - rule_table[i].rhs - 1;
287 short_tab[nrules] = nitems - rule_table[nrules].rhs - 1;
288 output_table_data (&output_obstack, short_tab,
289 0, 1, nrules + 1);
290 muscle_insert ("r2", obstack_finish (&output_obstack));
291 XFREE (short_tab);
292 }
293
294 /*------------------------------------------------------------------.
295 | Decide what to do for each type of token if seen as the lookahead |
296 | token in specified state. The value returned is used as the |
297 | default action (yydefact) for the state. In addition, actrow is |
298 | filled with what to do for each kind of token, index by symbol |
299 | number, with zero meaning do the default action. The value |
300 | MINSHORT, a very negative number, means this situation is an |
301 | error. The parser recognizes this value specially. |
302 | |
303 | This is where conflicts are resolved. The loop over lookahead |
304 | rules considered lower-numbered rules last, and the last rule |
305 | considered that likes a token gets to handle it. |
306 `------------------------------------------------------------------*/
307
308 static int
309 action_row (int state)
310 {
311 int i;
312 int j;
313 int k;
314 int m = 0;
315 int n = 0;
316 int default_rule;
317 int nreds;
318 int rule;
319 int shift_state;
320 int symbol;
321 reductions *redp;
322 shifts *shiftp;
323 errs *errp;
324 int nodefault = 0; /* set nonzero to inhibit having any default reduction */
325
326 for (i = 0; i < ntokens; i++)
327 actrow[i] = 0;
328
329 default_rule = 0;
330 nreds = 0;
331 redp = state_table[state]->reductions;
332
333 if (redp)
334 {
335 nreds = redp->nreds;
336
337 if (nreds >= 1)
338 {
339 /* loop over all the rules available here which require
340 lookahead */
341 m = state_table[state]->lookaheads;
342 n = state_table[state + 1]->lookaheads;
343
344 for (i = n - 1; i >= m; i--)
345 /* and find each token which the rule finds acceptable
346 to come next */
347 for (j = 0; j < ntokens; j++)
348 /* and record this rule as the rule to use if that
349 token follows. */
350 if (BITISSET (LA (i), j))
351 actrow[j] = -LAruleno[i];
352 }
353 }
354
355 /* Now see which tokens are allowed for shifts in this state. For
356 them, record the shift as the thing to do. So shift is preferred
357 to reduce. */
358 shiftp = state_table[state]->shifts;
359 for (i = 0; i < shiftp->nshifts; i++)
360 {
361 shift_state = shiftp->shifts[i];
362 if (!shift_state)
363 continue;
364
365 symbol = state_table[shift_state]->accessing_symbol;
366
367 if (ISVAR (symbol))
368 break;
369
370 actrow[symbol] = shift_state;
371
372 /* Do not use any default reduction if there is a shift for
373 error */
374 if (symbol == error_token_number)
375 nodefault = 1;
376 }
377
378 /* See which tokens are an explicit error in this state (due to
379 %nonassoc). For them, record MINSHORT as the action. */
380 errp = state_table[state]->errs;
381
382 if (errp)
383 {
384 k = errp->nerrs;
385
386 for (i = 0; i < k; i++)
387 {
388 symbol = errp->errs[i];
389 actrow[symbol] = MINSHORT;
390 }
391 }
392
393 /* Now find the most common reduction and make it the default action
394 for this state. */
395
396 if (nreds >= 1 && !nodefault)
397 {
398 if (state_table[state]->consistent)
399 default_rule = redp->rules[0];
400 else
401 {
402 int max = 0;
403 for (i = m; i < n; i++)
404 {
405 int count = 0;
406 rule = -LAruleno[i];
407
408 for (j = 0; j < ntokens; j++)
409 {
410 if (actrow[j] == rule)
411 count++;
412 }
413
414 if (count > max)
415 {
416 max = count;
417 default_rule = rule;
418 }
419 }
420
421 /* actions which match the default are replaced with zero,
422 which means "use the default" */
423
424 if (max > 0)
425 {
426 for (j = 0; j < ntokens; j++)
427 {
428 if (actrow[j] == default_rule)
429 actrow[j] = 0;
430 }
431
432 default_rule = -default_rule;
433 }
434 }
435 }
436
437 /* If have no default rule, the default is an error.
438 So replace any action which says "error" with "use default". */
439
440 if (default_rule == 0)
441 for (j = 0; j < ntokens; j++)
442 {
443 if (actrow[j] == MINSHORT)
444 actrow[j] = 0;
445 }
446
447 return default_rule;
448 }
449
450
451 static void
452 save_row (int state)
453 {
454 int i;
455 int count;
456 short *sp;
457 short *sp1;
458 short *sp2;
459
460 count = 0;
461 for (i = 0; i < ntokens; i++)
462 {
463 if (actrow[i] != 0)
464 count++;
465 }
466
467 if (count == 0)
468 return;
469
470 froms[state] = sp1 = sp = XCALLOC (short, count);
471 tos[state] = sp2 = XCALLOC (short, count);
472
473 for (i = 0; i < ntokens; i++)
474 {
475 if (actrow[i] != 0)
476 {
477 *sp1++ = i;
478 *sp2++ = actrow[i];
479 }
480 }
481
482 tally[state] = count;
483 width[state] = sp1[-1] - sp[0] + 1;
484 }
485
486
487 /*------------------------------------------------------------------.
488 | Figure out the actions for the specified state, indexed by |
489 | lookahead token type. |
490 | |
491 | The YYDEFACT table is output now. The detailed info is saved for |
492 | putting into YYTABLE later. |
493 `------------------------------------------------------------------*/
494
495 static void
496 token_actions (void)
497 {
498 int i;
499 short *yydefact = XCALLOC (short, nstates);
500
501 actrow = XCALLOC (short, ntokens);
502 for (i = 0; i < nstates; ++i)
503 {
504 yydefact[i] = action_row (i);
505 save_row (i);
506 }
507
508 output_table_data (&output_obstack, yydefact,
509 yydefact[0], 1, nstates);
510 muscle_insert ("defact", obstack_finish (&output_obstack));
511
512 XFREE (actrow);
513 XFREE (yydefact);
514 }
515
516
517 /*-----------------------------.
518 | Output the actions to OOUT. |
519 `-----------------------------*/
520
521 static void
522 actions_output (FILE *out)
523 {
524 int rule;
525 for (rule = 1; rule < nrules + 1; ++rule)
526 if (rule_table[rule].action)
527 {
528 fprintf (out, " case %d:\n", rule);
529
530 if (!no_lines_flag)
531 fprintf (out, muscle_find ("linef"),
532 rule_table[rule].action_line,
533 quotearg_style (c_quoting_style,
534 muscle_find ("filename")));
535 /* As a Bison extension, add the ending semicolon. Since some
536 Yacc don't do that, help people using bison as a Yacc
537 finding their missing semicolons. */
538 fprintf (out, "{ %s%s }\n break;\n\n",
539 rule_table[rule].action,
540 yacc_flag ? ";" : "");
541 }
542 }
543
544
545 static void
546 save_column (int symbol, int default_state)
547 {
548 int i;
549 short *sp;
550 short *sp1;
551 short *sp2;
552 int count;
553 int symno;
554
555 short begin = goto_map[symbol];
556 short end = goto_map[symbol + 1];
557
558 count = 0;
559 for (i = begin; i < end; i++)
560 {
561 if (to_state[i] != default_state)
562 count++;
563 }
564
565 if (count == 0)
566 return;
567
568 symno = symbol - ntokens + nstates;
569
570 froms[symno] = sp1 = sp = XCALLOC (short, count);
571 tos[symno] = sp2 = XCALLOC (short, count);
572
573 for (i = begin; i < end; i++)
574 {
575 if (to_state[i] != default_state)
576 {
577 *sp1++ = from_state[i];
578 *sp2++ = to_state[i];
579 }
580 }
581
582 tally[symno] = count;
583 width[symno] = sp1[-1] - sp[0] + 1;
584 }
585
586 static int
587 default_goto (int symbol)
588 {
589 int i;
590 int m;
591 int n;
592 int default_state;
593 int max;
594
595 m = goto_map[symbol];
596 n = goto_map[symbol + 1];
597
598 if (m == n)
599 return -1;
600
601 for (i = 0; i < nstates; i++)
602 state_count[i] = 0;
603
604 for (i = m; i < n; i++)
605 state_count[to_state[i]]++;
606
607 max = 0;
608 default_state = -1;
609
610 for (i = 0; i < nstates; i++)
611 {
612 if (state_count[i] > max)
613 {
614 max = state_count[i];
615 default_state = i;
616 }
617 }
618
619 return default_state;
620 }
621
622
623 /*-------------------------------------------------------------------.
624 | Figure out what to do after reducing with each rule, depending on |
625 | the saved state from before the beginning of parsing the data that |
626 | matched this rule. |
627 | |
628 | The YYDEFGOTO table is output now. The detailed info is saved for |
629 | putting into YYTABLE later. |
630 `-------------------------------------------------------------------*/
631
632 static void
633 goto_actions (void)
634 {
635 int i;
636 short *yydefgoto = XMALLOC (short, nsyms - ntokens);
637
638 state_count = XCALLOC (short, nstates);
639 for (i = ntokens; i < nsyms; ++i)
640 {
641 int default_state = default_goto (i);
642 save_column (i, default_state);
643 yydefgoto[i - ntokens] = default_state;
644 }
645
646 output_table_data (&output_obstack, yydefgoto,
647 yydefgoto[0], 1, nsyms - ntokens);
648 muscle_insert ("defgoto", obstack_finish (&output_obstack));
649
650 XFREE (state_count);
651 XFREE (yydefgoto);
652 }
653
654
655 /* The next few functions decide how to pack the actions and gotos
656 information into yytable. */
657
658 static void
659 sort_actions (void)
660 {
661 int i;
662 int j;
663 int k;
664 int t;
665 int w;
666
667 order = XCALLOC (short, nvectors);
668 nentries = 0;
669
670 for (i = 0; i < nvectors; i++)
671 {
672 if (tally[i] > 0)
673 {
674 t = tally[i];
675 w = width[i];
676 j = nentries - 1;
677
678 while (j >= 0 && (width[order[j]] < w))
679 j--;
680
681 while (j >= 0 && (width[order[j]] == w) && (tally[order[j]] < t))
682 j--;
683
684 for (k = nentries - 1; k > j; k--)
685 order[k + 1] = order[k];
686
687 order[j + 1] = i;
688 nentries++;
689 }
690 }
691 }
692
693
694 static int
695 matching_state (int vector)
696 {
697 int i;
698 int j;
699 int k;
700 int t;
701 int w;
702 int match;
703 int prev;
704
705 i = order[vector];
706 if (i >= nstates)
707 return -1;
708
709 t = tally[i];
710 w = width[i];
711
712 for (prev = vector - 1; prev >= 0; prev--)
713 {
714 j = order[prev];
715 if (width[j] != w || tally[j] != t)
716 return -1;
717
718 match = 1;
719 for (k = 0; match && k < t; k++)
720 {
721 if (tos[j][k] != tos[i][k] || froms[j][k] != froms[i][k])
722 match = 0;
723 }
724
725 if (match)
726 return j;
727 }
728
729 return -1;
730 }
731
732
733 static int
734 pack_vector (int vector)
735 {
736 int i;
737 int j;
738 int k;
739 int t;
740 int loc = 0;
741 int ok;
742 short *from;
743 short *to;
744
745 i = order[vector];
746 t = tally[i];
747
748 assert (t);
749
750 from = froms[i];
751 to = tos[i];
752
753 for (j = lowzero - from[0]; j < MAXTABLE; j++)
754 {
755 ok = 1;
756
757 for (k = 0; ok && k < t; k++)
758 {
759 loc = j + from[k];
760 if (loc > MAXTABLE)
761 fatal (_("maximum table size (%d) exceeded"), MAXTABLE);
762
763 if (table[loc] != 0)
764 ok = 0;
765 }
766
767 for (k = 0; ok && k < vector; k++)
768 {
769 if (pos[k] == j)
770 ok = 0;
771 }
772
773 if (ok)
774 {
775 for (k = 0; k < t; k++)
776 {
777 loc = j + from[k];
778 table[loc] = to[k];
779 check[loc] = from[k];
780 }
781
782 while (table[lowzero] != 0)
783 lowzero++;
784
785 if (loc > high)
786 high = loc;
787
788 return j;
789 }
790 }
791
792 assert (!"pack_vector");
793 return 0;
794 }
795
796
797 static void
798 pack_table (void)
799 {
800 int i;
801 int place;
802 int state;
803
804 base = XCALLOC (short, nvectors);
805 pos = XCALLOC (short, nentries);
806 table = XCALLOC (short, MAXTABLE);
807 check = XCALLOC (short, MAXTABLE);
808
809 lowzero = 0;
810 high = 0;
811
812 for (i = 0; i < nvectors; i++)
813 base[i] = MINSHORT;
814
815 for (i = 0; i < MAXTABLE; i++)
816 check[i] = -1;
817
818 for (i = 0; i < nentries; i++)
819 {
820 state = matching_state (i);
821
822 if (state < 0)
823 place = pack_vector (i);
824 else
825 place = base[state];
826
827 pos[i] = place;
828 base[order[i]] = place;
829 }
830
831 for (i = 0; i < nvectors; i++)
832 {
833 if (froms[i])
834 XFREE (froms[i]);
835 if (tos[i])
836 XFREE (tos[i]);
837 }
838
839 XFREE (froms);
840 XFREE (tos);
841 XFREE (pos);
842 }
843
844 /* the following functions output yytable, yycheck
845 and the vectors whose elements index the portion starts */
846
847 static void
848 output_base (void)
849 {
850 /* Output pact. */
851 output_table_data (&output_obstack, base,
852 base[0], 1, nstates);
853 muscle_insert ("pact", obstack_finish (&output_obstack));
854
855 /* Output pgoto. */
856 output_table_data (&output_obstack, base,
857 base[nstates], nstates + 1, nvectors);
858 muscle_insert ("pgoto", obstack_finish (&output_obstack));
859
860 XFREE (base);
861 }
862
863
864 static void
865 output_table (void)
866 {
867 output_table_data (&output_obstack, table,
868 table[0], 1, high + 1);
869 muscle_insert ("table", obstack_finish (&output_obstack));
870 XFREE (table);
871 }
872
873
874 static void
875 output_check (void)
876 {
877 output_table_data (&output_obstack, check,
878 check[0], 1, high + 1);
879 muscle_insert ("check", obstack_finish (&output_obstack));
880 XFREE (check);
881 }
882
883 /* compute and output yydefact, yydefgoto, yypact, yypgoto, yytable
884 and yycheck. */
885
886 static void
887 output_actions (void)
888 {
889 int i;
890 nvectors = nstates + nvars;
891
892 froms = XCALLOC (short *, nvectors);
893 tos = XCALLOC (short *, nvectors);
894 tally = XCALLOC (short, nvectors);
895 width = XCALLOC (short, nvectors);
896
897 token_actions ();
898 XFREE (LA);
899 XFREE (LAruleno);
900
901 goto_actions ();
902 XFREE (goto_map + ntokens);
903 XFREE (from_state);
904 XFREE (to_state);
905
906 sort_actions ();
907 pack_table ();
908
909 output_base ();
910 output_table ();
911
912 output_check ();
913
914 for (i = 0; i < nstates; ++i)
915 {
916 XFREE (state_table[i]->shifts);
917 XFREE (state_table[i]->reductions);
918 XFREE (state_table[i]->errs);
919 free (state_table[i]);
920 }
921 XFREE (state_table);
922 }
923
924 \f
925 /*------------------------------------------------------------.
926 | Copy the parser code from SKEL_FILENAME into OOUT obstack. |
927 | and do the muscle substitution. |
928 `------------------------------------------------------------*/
929
930 static void
931 output_parser (const char *skel_filename, FILE *out)
932 {
933 int c;
934 FILE *fskel;
935 size_t line;
936
937 fskel = xfopen (skel_filename, "r");
938
939 /* New output code. */
940 line = 1;
941 c = getc (fskel);
942 while (c != EOF)
943 {
944 if (c != '%')
945 {
946 if (c == '\n')
947 ++line;
948 putc (c, out);
949 c = getc (fskel);
950 }
951 else if ((c = getc (fskel)) == '%')
952 {
953 /* Read the muscle. */
954 const char *muscle_key = 0;
955 const char *muscle_value = 0;
956
957 while (isalnum (c = getc (fskel)) || c == '-')
958 obstack_1grow (&muscle_obstack, c);
959 obstack_1grow (&muscle_obstack, 0);
960
961 /* Output the right value, or see if it's something special. */
962 muscle_key = obstack_finish (&muscle_obstack);
963 muscle_value = muscle_find (muscle_key);
964 if (!strcmp (muscle_key, "actions"))
965 actions_output (out);
966 else if (!strcmp (muscle_key, "line"))
967 fprintf (out, "%d", line + 1);
968 else if (muscle_value)
969 fputs (muscle_value, out);
970 else
971 {
972 fputs ("%%", out);
973 fputs (muscle_key, out);
974 }
975 }
976 else
977 putc ('%', out);
978 }
979
980 /* End. */
981 xfclose (fskel);
982 }
983
984 /*----------------------------------------.
985 | Prepare the master parser to be output |
986 `----------------------------------------*/
987
988 static void
989 output_master_parser (void)
990 {
991 FILE *parser = xfopen (parser_file_name, "w");
992 if (!skeleton)
993 {
994 if (semantic_parser)
995 skeleton = skeleton_find ("BISON_HAIRY", BISON_HAIRY);
996 else
997 skeleton = skeleton_find ("BISON_SIMPLE", BISON_SIMPLE);
998 }
999 muscle_insert ("skeleton", skeleton);
1000
1001 output_parser (skeleton, parser);
1002 xfclose (parser);
1003 }
1004
1005
1006 /* FIXME. */
1007
1008 #define MUSCLE_INSERT_INT(Key, Value) \
1009 { \
1010 obstack_fgrow1 (&muscle_obstack, "%d", Value); \
1011 obstack_1grow (&muscle_obstack, 0); \
1012 muscle_insert (Key, obstack_finish (&muscle_obstack)); \
1013 }
1014
1015 #define MUSCLE_INSERT_STRING(Key, Value) \
1016 { \
1017 obstack_sgrow (&muscle_obstack, Value); \
1018 obstack_1grow (&muscle_obstack, 0); \
1019 muscle_insert (Key, obstack_finish (&muscle_obstack)); \
1020 }
1021
1022 #define MUSCLE_INSERT_PREFIX(Key, Value) \
1023 { \
1024 obstack_fgrow2 (&muscle_obstack, "%s%s", spec_name_prefix, Value); \
1025 obstack_1grow (&muscle_obstack, 0); \
1026 muscle_insert (Key, obstack_finish (&muscle_obstack)); \
1027 }
1028
1029 static void
1030 prepare (void)
1031 {
1032 MUSCLE_INSERT_INT ("last", high);
1033 MUSCLE_INSERT_INT ("flag", MINSHORT);
1034 MUSCLE_INSERT_INT ("pure", pure_parser);
1035 MUSCLE_INSERT_INT ("nsym", nsyms);
1036 MUSCLE_INSERT_INT ("debug", debug_flag);
1037 MUSCLE_INSERT_INT ("final", final_state);
1038 MUSCLE_INSERT_INT ("maxtok", max_user_token_number);
1039 MUSCLE_INSERT_INT ("ntbase", ntokens);
1040 MUSCLE_INSERT_INT ("error-verbose", error_verbose);
1041 MUSCLE_INSERT_STRING ("prefix", spec_name_prefix);
1042
1043 MUSCLE_INSERT_INT ("nnts", nvars);
1044 MUSCLE_INSERT_INT ("nrules", nrules);
1045 MUSCLE_INSERT_INT ("nstates", nstates);
1046 MUSCLE_INSERT_INT ("ntokens", ntokens);
1047
1048 MUSCLE_INSERT_INT ("locations-flag", locations_flag);
1049 }
1050
1051
1052 /*-------------------------.
1053 | Output the header file. |
1054 `-------------------------*/
1055
1056 static void
1057 header_output (void)
1058 {
1059 FILE *out = xfopen (spec_defines_file, "w");
1060 char *macro_name = compute_header_macro ();
1061
1062 fprintf (out, "#ifndef %s\n", macro_name);
1063 fprintf (out, "# define %s\n\n", macro_name);
1064
1065 fputs (muscle_find ("tokendef"), out);
1066 fprintf (out, "\
1067 #ifndef YYSTYPE\n\
1068 typedef %s
1069 yystype;\n\
1070 # define YYSTYPE yystype\n\
1071 #endif\n",
1072 muscle_find ("stype"));
1073
1074 if (!pure_parser)
1075 fprintf (out, "\nextern YYSTYPE %slval;\n",
1076 spec_name_prefix);
1077 if (semantic_parser)
1078 {
1079 int i;
1080
1081 for (i = ntokens; i < nsyms; i++)
1082 /* don't make these for dummy nonterminals made by gensym. */
1083 if (*tags[i] != '@')
1084 fprintf (out, "# define\tNT%s\t%d\n", tags[i], i);
1085 }
1086
1087 fprintf (out, "\n#endif /* not %s */\n", macro_name);
1088 free (macro_name);
1089 xfclose (out);
1090 }
1091
1092
1093 /*----------------------------------------------------------.
1094 | Output the parsing tables and the parser code to ftable. |
1095 `----------------------------------------------------------*/
1096
1097 void
1098 output (void)
1099 {
1100 obstack_init (&output_obstack);
1101
1102 output_token_translations ();
1103 output_gram ();
1104
1105 XFREE (ritem);
1106 if (semantic_parser)
1107 output_stos ();
1108 output_rule_data ();
1109 XFREE (user_toknums);
1110 output_actions ();
1111
1112 prepare ();
1113 /* Copy definitions in directive. */
1114 obstack_1grow (&attrs_obstack, 0);
1115 muscle_insert ("prologue", obstack_finish (&attrs_obstack));
1116
1117 /* Output the parser. */
1118 output_master_parser ();
1119 /* Output the header if needed. */
1120 if (defines_flag)
1121 header_output ();
1122
1123 free (rule_table + 1);
1124 obstack_free (&muscle_obstack, 0);
1125 obstack_free (&output_obstack, 0);
1126 obstack_free (&action_obstack, 0);
1127 }