]> git.saurik.com Git - bison.git/blob - src/output.c
* src/warshall.c (TC, RTC): De-obsfucate (source reduced to 22% 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 int error_verbose = 0;
129
130 /* FIXME. */
131
132 static inline void
133 output_table_data (struct obstack *oout,
134 short *table_data,
135 short first,
136 short begin,
137 short end)
138 {
139 int i;
140 int j = 1;
141
142 obstack_fgrow1 (oout, "%6d", first);
143 for (i = begin; i < end; ++i)
144 {
145 obstack_1grow (oout, ',');
146 if (j >= 10)
147 {
148 obstack_sgrow (oout, "\n ");
149 j = 1;
150 }
151 else
152 ++j;
153 obstack_fgrow1 (oout, "%6d", table_data[i]);
154 }
155 obstack_1grow (oout, 0);
156 }
157
158
159 static void
160 output_token_translations (void)
161 {
162 output_table_data (&output_obstack, token_translations,
163 0, 1, max_user_token_number + 1);
164 muscle_insert ("translate", obstack_finish (&output_obstack));
165 XFREE (token_translations);
166 }
167
168
169 static void
170 output_gram (void)
171 {
172 {
173 int i;
174 short *values = XCALLOC (short, nrules + 1);
175 for (i = 0; i < nrules + 1; ++i)
176 values[i] = rule_table[i].rhs;
177 output_table_data (&output_obstack, values,
178 0, 1, nrules + 1);
179 XFREE (values);
180 }
181
182 muscle_insert ("prhs", obstack_finish (&output_obstack));
183
184 {
185 size_t yyrhs_size = 1;
186 short *yyrhs, *sp;
187 int i;
188
189 for (sp = ritem + 1; *sp; sp++)
190 ++yyrhs_size;
191 yyrhs = XMALLOC (short, yyrhs_size);
192
193 for (sp = ritem + 1, i = 1; *sp; ++sp, ++i)
194 yyrhs[i] = *sp > 0 ? *sp : 0;
195
196 output_table_data (&output_obstack, yyrhs,
197 ritem[0], 1, yyrhs_size);
198 muscle_insert ("rhs", obstack_finish (&output_obstack));
199
200 XFREE (yyrhs);
201 }
202
203 #if 0
204 if (!semantic_parser && !no_parser_flag)
205 obstack_sgrow (&table_obstack, "\n#endif\n");
206 #endif
207 }
208
209
210 static void
211 output_stos (void)
212 {
213 int i;
214 short *values = (short *) alloca (sizeof (short) * nstates);
215 for (i = 0; i < nstates; ++i)
216 values[i] = state_table[i].accessing_symbol;
217 output_table_data (&output_obstack, values,
218 0, 1, nstates);
219 muscle_insert ("stos", obstack_finish (&output_obstack));
220 }
221
222
223 static void
224 output_rule_data (void)
225 {
226 int i;
227 int j;
228 short *short_tab = NULL;
229
230 {
231 short *values = XCALLOC (short, nrules + 1);
232 for (i = 0; i < nrules + 1; ++i)
233 values[i] = rule_table[i].line;
234 output_table_data (&output_obstack, values,
235 0, 1, nrules + 1);
236 muscle_insert ("rline", obstack_finish (&output_obstack));
237 XFREE (values);
238 }
239
240
241 j = 0;
242 for (i = 0; i < nsyms; i++)
243 /* this used to be i<=nsyms, but that output a final "" symbol
244 almost by accident */
245 {
246 /* Width of the next token, including the two quotes, the coma
247 and the space. */
248 int strsize = 4;
249 char *p;
250
251 for (p = tags[i]; p && *p; p++)
252 if (*p == '"' || *p == '\\' || *p == '\n' || *p == '\t'
253 || *p == '\b')
254 strsize += 2;
255 else if (*p < 040 || *p >= 0177)
256 strsize += 4;
257 else
258 strsize++;
259
260 if (j + strsize > 75)
261 {
262 obstack_sgrow (&output_obstack, "\n ");
263 j = 2;
264 }
265
266 obstack_1grow (&output_obstack, '\"');
267 for (p = tags[i]; p && *p; p++)
268 {
269 if (*p == '"' || *p == '\\')
270 obstack_fgrow1 (&output_obstack, "\\%c", *p);
271 else if (*p == '\n')
272 obstack_sgrow (&output_obstack, "\\n");
273 else if (*p == '\t')
274 obstack_sgrow (&output_obstack, "\\t");
275 else if (*p == '\b')
276 obstack_sgrow (&output_obstack, "\\b");
277 else if (*p < 040 || *p >= 0177)
278 obstack_fgrow1 (&output_obstack, "\\%03o", *p);
279 else
280 obstack_1grow (&output_obstack, *p);
281 }
282
283 obstack_sgrow (&output_obstack, "\", ");
284 j += strsize;
285 }
286 /* add a NULL entry to list of tokens */
287 obstack_sgrow (&output_obstack, "NULL");
288
289 /* Finish table and store. */
290 obstack_1grow (&output_obstack, 0);
291 muscle_insert ("tname", obstack_finish (&output_obstack));
292
293 /* Output YYTOKNUM. */
294 output_table_data (&output_obstack, user_toknums,
295 0, 1, ntokens + 1);
296 muscle_insert ("toknum", obstack_finish (&output_obstack));
297
298 /* Output YYR1. */
299 {
300 short *values = XCALLOC (short, nrules + 1);
301 for (i = 0; i < nrules + 1; ++i)
302 values[i] = rule_table[i].lhs;
303 output_table_data (&output_obstack, values,
304 0, 1, nrules + 1);
305 muscle_insert ("r1", obstack_finish (&output_obstack));
306 XFREE (values);
307 }
308
309 /* Output YYR2. */
310 short_tab = XMALLOC (short, nrules + 1);
311 for (i = 1; i < nrules; i++)
312 short_tab[i] = rule_table[i + 1].rhs - rule_table[i].rhs - 1;
313 short_tab[nrules] = nitems - rule_table[nrules].rhs - 1;
314 output_table_data (&output_obstack, short_tab,
315 0, 1, nrules + 1);
316 muscle_insert ("r2", obstack_finish (&output_obstack));
317 XFREE (short_tab);
318
319 XFREE (rule_table + 1);
320 }
321
322 /*------------------------------------------------------------------.
323 | Decide what to do for each type of token if seen as the lookahead |
324 | token in specified state. The value returned is used as the |
325 | default action (yydefact) for the state. In addition, actrow is |
326 | filled with what to do for each kind of token, index by symbol |
327 | number, with zero meaning do the default action. The value |
328 | MINSHORT, a very negative number, means this situation is an |
329 | error. The parser recognizes this value specially. |
330 | |
331 | This is where conflicts are resolved. The loop over lookahead |
332 | rules considered lower-numbered rules last, and the last rule |
333 | considered that likes a token gets to handle it. |
334 `------------------------------------------------------------------*/
335
336 static int
337 action_row (int state)
338 {
339 int i;
340 int j;
341 int k;
342 int m = 0;
343 int n = 0;
344 int default_rule;
345 int nreds;
346 int rule;
347 int shift_state;
348 int symbol;
349 reductions *redp;
350 shifts *shiftp;
351 errs *errp;
352 int nodefault = 0; /* set nonzero to inhibit having any default reduction */
353
354 for (i = 0; i < ntokens; i++)
355 actrow[i] = 0;
356
357 default_rule = 0;
358 nreds = 0;
359 redp = state_table[state].reduction_table;
360
361 if (redp)
362 {
363 nreds = redp->nreds;
364
365 if (nreds >= 1)
366 {
367 /* loop over all the rules available here which require
368 lookahead */
369 m = state_table[state].lookaheads;
370 n = state_table[state + 1].lookaheads;
371
372 for (i = n - 1; i >= m; i--)
373 /* and find each token which the rule finds acceptable
374 to come next */
375 for (j = 0; j < ntokens; j++)
376 /* and record this rule as the rule to use if that
377 token follows. */
378 if (BITISSET (LA (i), j))
379 actrow[j] = -LAruleno[i];
380 }
381 }
382
383 /* Now see which tokens are allowed for shifts in this state. For
384 them, record the shift as the thing to do. So shift is preferred
385 to reduce. */
386 shiftp = state_table[state].shift_table;
387 for (i = 0; i < shiftp->nshifts; i++)
388 {
389 shift_state = shiftp->shifts[i];
390 if (!shift_state)
391 continue;
392
393 symbol = state_table[shift_state].accessing_symbol;
394
395 if (ISVAR (symbol))
396 break;
397
398 actrow[symbol] = shift_state;
399
400 /* Do not use any default reduction if there is a shift for
401 error */
402 if (symbol == error_token_number)
403 nodefault = 1;
404 }
405
406 /* See which tokens are an explicit error in this state (due to
407 %nonassoc). For them, record MINSHORT as the action. */
408 errp = err_table[state];
409
410 if (errp)
411 {
412 k = errp->nerrs;
413
414 for (i = 0; i < k; i++)
415 {
416 symbol = errp->errs[i];
417 actrow[symbol] = MINSHORT;
418 }
419 }
420
421 /* Now find the most common reduction and make it the default action
422 for this state. */
423
424 if (nreds >= 1 && !nodefault)
425 {
426 if (state_table[state].consistent)
427 default_rule = redp->rules[0];
428 else
429 {
430 int max = 0;
431 for (i = m; i < n; i++)
432 {
433 int count = 0;
434 rule = -LAruleno[i];
435
436 for (j = 0; j < ntokens; j++)
437 {
438 if (actrow[j] == rule)
439 count++;
440 }
441
442 if (count > max)
443 {
444 max = count;
445 default_rule = rule;
446 }
447 }
448
449 /* actions which match the default are replaced with zero,
450 which means "use the default" */
451
452 if (max > 0)
453 {
454 for (j = 0; j < ntokens; j++)
455 {
456 if (actrow[j] == default_rule)
457 actrow[j] = 0;
458 }
459
460 default_rule = -default_rule;
461 }
462 }
463 }
464
465 /* If have no default rule, the default is an error.
466 So replace any action which says "error" with "use default". */
467
468 if (default_rule == 0)
469 for (j = 0; j < ntokens; j++)
470 {
471 if (actrow[j] == MINSHORT)
472 actrow[j] = 0;
473 }
474
475 return default_rule;
476 }
477
478
479 static void
480 save_row (int state)
481 {
482 int i;
483 int count;
484 short *sp;
485 short *sp1;
486 short *sp2;
487
488 count = 0;
489 for (i = 0; i < ntokens; i++)
490 {
491 if (actrow[i] != 0)
492 count++;
493 }
494
495 if (count == 0)
496 return;
497
498 froms[state] = sp1 = sp = XCALLOC (short, count);
499 tos[state] = sp2 = XCALLOC (short, count);
500
501 for (i = 0; i < ntokens; i++)
502 {
503 if (actrow[i] != 0)
504 {
505 *sp1++ = i;
506 *sp2++ = actrow[i];
507 }
508 }
509
510 tally[state] = count;
511 width[state] = sp1[-1] - sp[0] + 1;
512 }
513
514
515 /*------------------------------------------------------------------.
516 | Figure out the actions for the specified state, indexed by |
517 | lookahead token type. |
518 | |
519 | The YYDEFACT table is output now. The detailed info is saved for |
520 | putting into YYTABLE later. |
521 `------------------------------------------------------------------*/
522
523 static void
524 token_actions (void)
525 {
526 int i;
527 short *yydefact = XCALLOC (short, nstates);
528
529 actrow = XCALLOC (short, ntokens);
530 for (i = 0; i < nstates; ++i)
531 {
532 yydefact[i] = action_row (i);
533 save_row (i);
534 }
535
536 output_table_data (&output_obstack, yydefact,
537 yydefact[0], 1, nstates);
538 muscle_insert ("defact", obstack_finish (&output_obstack));
539
540 XFREE (actrow);
541 XFREE (yydefact);
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 berror ("pack_vector");
793 return 0; /* JF keep lint happy */
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 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 LIST_FREE (shifts, first_shift);
898 LIST_FREE (reductions, first_reduction);
899 XFREE (LA);
900 XFREE (LAruleno);
901
902 goto_actions ();
903 XFREE (goto_map + ntokens);
904 XFREE (from_state);
905 XFREE (to_state);
906
907 sort_actions ();
908 pack_table ();
909
910 output_base ();
911 output_table ();
912
913 output_check ();
914 XFREE (state_table);
915 }
916
917 \f
918 /*------------------------------------------------------------.
919 | Copy the parser code from SKEL_FILENAME into OOUT obstack. |
920 | and do the muscle substitution. |
921 `------------------------------------------------------------*/
922
923 static void
924 output_parser (const char *skel_filename, struct obstack *oout)
925 {
926 int c;
927 FILE *fskel;
928 size_t line;
929
930 fskel = xfopen (skel_filename, "r");
931
932 /* New output code. */
933 line = 1;
934 c = getc (fskel);
935 while (c != EOF)
936 {
937 if (c != '%')
938 {
939 if (c == '\n')
940 ++line;
941 obstack_1grow (oout, c);
942 c = getc (fskel);
943 }
944 else if ((c = getc (fskel)) == '%')
945 {
946 /* Read the muscle. */
947 const char *muscle_key = 0;
948 const char *muscle_value = 0;
949
950 while (isalnum (c = getc (fskel)) || c == '-')
951 obstack_1grow (&muscle_obstack, c);
952 obstack_1grow (&muscle_obstack, 0);
953
954 /* Output the right value, or see if it's something special. */
955 muscle_key = obstack_finish (&muscle_obstack);
956 muscle_value = muscle_find (muscle_key);
957 if (muscle_value)
958 obstack_sgrow (oout, muscle_value);
959 else if (!strcmp (muscle_key, "line"))
960 obstack_fgrow1 (oout, "%d", line + 1);
961 else if (!strcmp (muscle_key, "input-line"))
962 obstack_fgrow1 (oout, "%d", lineno);
963 else
964 {
965 obstack_sgrow (oout, "%%");
966 obstack_sgrow (oout, muscle_key);
967 }
968 }
969 else
970 obstack_1grow (oout, '%');
971 }
972
973 /* End. */
974 xfclose (fskel);
975 }
976
977 /*----------------------------------------.
978 | Prepare the master parser to be output |
979 `----------------------------------------*/
980
981 static void
982 output_master_parser (void)
983 {
984 if (!skeleton)
985 {
986 if (semantic_parser)
987 skeleton = skeleton_find ("BISON_HAIRY", BISON_HAIRY);
988 else
989 skeleton = skeleton_find ("BISON_SIMPLE", BISON_SIMPLE);
990 }
991 muscle_insert ("skeleton", skeleton);
992 output_parser (skeleton, &table_obstack);
993 }
994
995
996 /* FIXME. */
997
998 #define MUSCLE_INSERT_INT(Key, Value) \
999 { \
1000 obstack_fgrow1 (&muscle_obstack, "%d", Value); \
1001 obstack_1grow (&muscle_obstack, 0); \
1002 muscle_insert (Key, obstack_finish (&muscle_obstack)); \
1003 }
1004
1005 #define MUSCLE_INSERT_STRING(Key, Value) \
1006 { \
1007 obstack_sgrow (&muscle_obstack, Value); \
1008 obstack_1grow (&muscle_obstack, 0); \
1009 muscle_insert (Key, obstack_finish (&muscle_obstack)); \
1010 }
1011
1012 #define MUSCLE_INSERT_PREFIX(Key, Value) \
1013 { \
1014 obstack_fgrow2 (&muscle_obstack, "%s%s", spec_name_prefix, Value); \
1015 obstack_1grow (&muscle_obstack, 0); \
1016 muscle_insert (Key, obstack_finish (&muscle_obstack)); \
1017 }
1018
1019 static void
1020 prepare (void)
1021 {
1022 MUSCLE_INSERT_INT ("last", high);
1023 MUSCLE_INSERT_INT ("flag", MINSHORT);
1024 MUSCLE_INSERT_INT ("pure", pure_parser);
1025 MUSCLE_INSERT_INT ("nsym", nsyms);
1026 MUSCLE_INSERT_INT ("debug", debug_flag);
1027 MUSCLE_INSERT_INT ("final", final_state);
1028 MUSCLE_INSERT_INT ("maxtok", max_user_token_number);
1029 MUSCLE_INSERT_INT ("ntbase", ntokens);
1030 MUSCLE_INSERT_INT ("error-verbose", error_verbose);
1031
1032 MUSCLE_INSERT_INT ("nnts", nvars);
1033 MUSCLE_INSERT_INT ("nrules", nrules);
1034 MUSCLE_INSERT_INT ("nstates", nstates);
1035 MUSCLE_INSERT_INT ("ntokens", ntokens);
1036
1037 MUSCLE_INSERT_INT ("locations-flag", locations_flag);
1038
1039 /* We need to save the actions in the muscle %%action. */
1040 muscle_insert ("action", obstack_finish (&action_obstack));
1041
1042 if (spec_name_prefix)
1043 MUSCLE_INSERT_STRING ("prefix", spec_name_prefix);
1044 }
1045
1046 /*----------------------------------------------------------.
1047 | Output the parsing tables and the parser code to ftable. |
1048 `----------------------------------------------------------*/
1049
1050 void
1051 output (void)
1052 {
1053 obstack_init (&output_obstack);
1054
1055 LIST_FREE (core, first_state);
1056
1057 output_token_translations ();
1058 output_gram ();
1059
1060 XFREE (ritem);
1061 if (semantic_parser)
1062 output_stos ();
1063 output_rule_data ();
1064 XFREE (user_toknums);
1065 output_actions ();
1066
1067 #if 0
1068 if (!no_parser_flag) */
1069 #endif
1070 prepare ();
1071 /* Copy definitions in directive. */
1072 muscle_insert ("prologue", obstack_finish (&attrs_obstack));
1073
1074 output_master_parser ();
1075
1076 obstack_free (&muscle_obstack, 0);
1077 obstack_free (&output_obstack, 0);
1078 obstack_free (&action_obstack, 0);
1079 }