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