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