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