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