xref: /openbsd/usr.bin/yacc/output.c (revision 891d7ab6)
1 /*	$OpenBSD: output.c,v 1.15 2009/10/27 23:59:50 deraadt Exp $	*/
2 /*	$NetBSD: output.c,v 1.4 1996/03/19 03:21:41 jtc Exp $	*/
3 
4 /*
5  * Copyright (c) 1989 The Regents of the University of California.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Robert Paul Corbett.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include "defs.h"
37 
38 static int nvectors;
39 static int nentries;
40 static short **froms;
41 static short **tos;
42 static short *tally;
43 static short *width;
44 static short *state_count;
45 static short *order;
46 static short *base;
47 static short *pos;
48 static int maxtable;
49 static short *table;
50 static short *check;
51 static int lowzero;
52 static int high;
53 
54 void output_prefix(void);
55 void output_rule_data(void);
56 void output_yydefred(void);
57 void output_actions(void);
58 void token_actions(void);
59 void goto_actions(void);
60 int default_goto(int);
61 void save_column(int, int);
62 void sort_actions(void);
63 void pack_table(void);
64 int matching_vector(int);
65 int pack_vector(int);
66 void output_base(void);
67 void output_table(void);
68 void output_check(void);
69 int is_C_identifier(char *);
70 void output_defines(void);
71 void output_stored_text(void);
72 void output_debug(void);
73 void output_stype(void);
74 void output_trailing_text(void);
75 void output_semantic_actions(void);
76 void free_itemsets(void);
77 void free_shifts(void);
78 void free_reductions(void);
79 
80 void
81 output(void)
82 {
83     free_itemsets();
84     free_shifts();
85     free_reductions();
86     output_prefix();
87     output_stored_text();
88     output_defines();
89     output_rule_data();
90     output_yydefred();
91     output_actions();
92     free_parser();
93     output_debug();
94     output_stype();
95     if (rflag) write_section(tables);
96     write_section(header);
97     output_trailing_text();
98     write_section(body);
99     output_semantic_actions();
100     write_section(trailer);
101 }
102 
103 
104 void
105 output_prefix(void)
106 {
107     if (symbol_prefix == NULL)
108 	symbol_prefix = "yy";
109     else
110     {
111 	++outline;
112 	fprintf(code_file, "#define yyparse %sparse\n", symbol_prefix);
113 	++outline;
114 	fprintf(code_file, "#define yylex %slex\n", symbol_prefix);
115 	++outline;
116 	fprintf(code_file, "#define yyerror %serror\n", symbol_prefix);
117 	++outline;
118 	fprintf(code_file, "#define yychar %schar\n", symbol_prefix);
119 	++outline;
120 	fprintf(code_file, "#define yyval %sval\n", symbol_prefix);
121 	++outline;
122 	fprintf(code_file, "#define yylval %slval\n", symbol_prefix);
123 	++outline;
124 	fprintf(code_file, "#define yydebug %sdebug\n", symbol_prefix);
125 	++outline;
126 	fprintf(code_file, "#define yynerrs %snerrs\n", symbol_prefix);
127 	++outline;
128 	fprintf(code_file, "#define yyerrflag %serrflag\n", symbol_prefix);
129 	++outline;
130 	fprintf(code_file, "#define yyss %sss\n", symbol_prefix);
131 	++outline;
132 	fprintf(code_file, "#define yysslim %ssslim\n", symbol_prefix);
133 	++outline;
134 	fprintf(code_file, "#define yyssp %sssp\n", symbol_prefix);
135 	++outline;
136 	fprintf(code_file, "#define yyvs %svs\n", symbol_prefix);
137 	++outline;
138 	fprintf(code_file, "#define yyvsp %svsp\n", symbol_prefix);
139 	++outline;
140 	fprintf(code_file, "#define yystacksize %sstacksize\n", symbol_prefix);
141 	++outline;
142 	fprintf(code_file, "#define yylhs %slhs\n", symbol_prefix);
143 	++outline;
144 	fprintf(code_file, "#define yylen %slen\n", symbol_prefix);
145 	++outline;
146 	fprintf(code_file, "#define yydefred %sdefred\n", symbol_prefix);
147 	++outline;
148 	fprintf(code_file, "#define yydgoto %sdgoto\n", symbol_prefix);
149 	++outline;
150 	fprintf(code_file, "#define yysindex %ssindex\n", symbol_prefix);
151 	++outline;
152 	fprintf(code_file, "#define yyrindex %srindex\n", symbol_prefix);
153 	++outline;
154 	fprintf(code_file, "#define yygindex %sgindex\n", symbol_prefix);
155 	++outline;
156 	fprintf(code_file, "#define yytable %stable\n", symbol_prefix);
157 	++outline;
158 	fprintf(code_file, "#define yycheck %scheck\n", symbol_prefix);
159 	++outline;
160 	fprintf(code_file, "#define yyname %sname\n", symbol_prefix);
161 	++outline;
162 	fprintf(code_file, "#define yyrule %srule\n", symbol_prefix);
163     }
164     ++outline;
165     fprintf(code_file, "#define YYPREFIX \"%s\"\n", symbol_prefix);
166 }
167 
168 
169 void
170 output_rule_data(void)
171 {
172     int i;
173     int j;
174 
175     fprintf(output_file,
176 	"#if defined(__cplusplus) || defined(__STDC__)\n"
177 	"const short %slhs[] =\n"
178 	"#else\n"
179 	"short %slhs[] =\n"
180 	"#endif\n"
181 	"\t{%42d,", symbol_prefix, symbol_prefix, symbol_value[start_symbol]);
182 
183     j = 10;
184     for (i = 3; i < nrules; i++)
185     {
186 	if (j >= 10)
187 	{
188 	    if (!rflag) ++outline;
189 	    putc('\n', output_file);
190 	    j = 1;
191 	}
192         else
193 	    ++j;
194 
195         fprintf(output_file, "%5d,", symbol_value[rlhs[i]]);
196     }
197     if (!rflag) outline += 2;
198     fprintf(output_file, "\n};\n");
199 
200     fprintf(output_file,
201 	"#if defined(__cplusplus) || defined(__STDC__)\n"
202 	"const short %slen[] =\n"
203 	"#else\n"
204 	"short %slen[] =\n"
205 	"#endif\n"
206 	"\t{%42d,", symbol_prefix, symbol_prefix, 2);
207 
208     j = 10;
209     for (i = 3; i < nrules; i++)
210     {
211 	if (j >= 10)
212 	{
213 	    if (!rflag) ++outline;
214 	    putc('\n', output_file);
215 	    j = 1;
216 	}
217 	else
218 	  j++;
219 
220         fprintf(output_file, "%5d,", rrhs[i + 1] - rrhs[i] - 1);
221     }
222     if (!rflag) outline += 2;
223     fprintf(output_file, "\n};\n");
224 }
225 
226 
227 void
228 output_yydefred(void)
229 {
230     int i, j;
231 
232     fprintf(output_file,
233 	"#if defined(__cplusplus) || defined(__STDC__)\n"
234 	"const short %sdefred[] =\n"
235 	"#else\n"
236 	"short %sdefred[] =\n"
237 	"#endif\n"
238 	"\t{%39d,",
239 	symbol_prefix, symbol_prefix, (defred[0] ? defred[0] - 2 : 0));
240 
241     j = 10;
242     for (i = 1; i < nstates; i++)
243     {
244 	if (j < 10)
245 	    ++j;
246 	else
247 	{
248 	    if (!rflag) ++outline;
249 	    putc('\n', output_file);
250 	    j = 1;
251 	}
252 
253 	fprintf(output_file, "%5d,", (defred[i] ? defred[i] - 2 : 0));
254     }
255 
256     if (!rflag) outline += 2;
257     fprintf(output_file, "\n};\n");
258 }
259 
260 
261 void
262 output_actions(void)
263 {
264     nvectors = 2*nstates + nvars;
265 
266     froms = NEW2(nvectors, short *);
267     tos = NEW2(nvectors, short *);
268     tally = NEW2(nvectors, short);
269     width = NEW2(nvectors, short);
270 
271     token_actions();
272     FREE(lookaheads);
273     FREE(LA);
274     FREE(LAruleno);
275     FREE(accessing_symbol);
276 
277     goto_actions();
278     FREE(goto_map + ntokens);
279     FREE(from_state);
280     FREE(to_state);
281 
282     sort_actions();
283     pack_table();
284     output_base();
285     output_table();
286     output_check();
287 }
288 
289 
290 void
291 token_actions(void)
292 {
293     int i, j;
294     int shiftcount, reducecount;
295     int max, min;
296     short *actionrow, *r, *s;
297     action *p;
298 
299     actionrow = NEW2(2*ntokens, short);
300     for (i = 0; i < nstates; ++i)
301     {
302 	if (parser[i])
303 	{
304 	    for (j = 0; j < 2*ntokens; ++j)
305 	    actionrow[j] = 0;
306 
307 	    shiftcount = 0;
308 	    reducecount = 0;
309 	    for (p = parser[i]; p; p = p->next)
310 	    {
311 		if (p->suppressed == 0)
312 		{
313 		    if (p->action_code == SHIFT)
314 		    {
315 			++shiftcount;
316 			actionrow[p->symbol] = p->number;
317 		    }
318 		    else if (p->action_code == REDUCE && p->number != defred[i])
319 		    {
320 			++reducecount;
321 			actionrow[p->symbol + ntokens] = p->number;
322 		    }
323 		}
324 	    }
325 
326 	    tally[i] = shiftcount;
327 	    tally[nstates+i] = reducecount;
328 	    width[i] = 0;
329 	    width[nstates+i] = 0;
330 	    if (shiftcount > 0)
331 	    {
332 		froms[i] = r = NEW2(shiftcount, short);
333 		tos[i] = s = NEW2(shiftcount, short);
334 		min = MAXSHORT;
335 		max = 0;
336 		for (j = 0; j < ntokens; ++j)
337 		{
338 		    if (actionrow[j])
339 		    {
340 			if (min > symbol_value[j])
341 			    min = symbol_value[j];
342 			if (max < symbol_value[j])
343 			    max = symbol_value[j];
344 			*r++ = symbol_value[j];
345 			*s++ = actionrow[j];
346 		    }
347 		}
348 		width[i] = max - min + 1;
349 	    }
350 	    if (reducecount > 0)
351 	    {
352 		froms[nstates+i] = r = NEW2(reducecount, short);
353 		tos[nstates+i] = s = NEW2(reducecount, short);
354 		min = MAXSHORT;
355 		max = 0;
356 		for (j = 0; j < ntokens; ++j)
357 		{
358 		    if (actionrow[ntokens+j])
359 		    {
360 			if (min > symbol_value[j])
361 			    min = symbol_value[j];
362 			if (max < symbol_value[j])
363 			    max = symbol_value[j];
364 			*r++ = symbol_value[j];
365 			*s++ = actionrow[ntokens+j] - 2;
366 		    }
367 		}
368 		width[nstates+i] = max - min + 1;
369 	    }
370 	}
371     }
372     FREE(actionrow);
373 }
374 
375 void
376 goto_actions(void)
377 {
378     int i, j, k;
379 
380     state_count = NEW2(nstates, short);
381 
382     k = default_goto(start_symbol + 1);
383     fprintf(output_file,
384 	"#if defined(__cplusplus) || defined(__STDC__)\n"
385 	"const short %sdgoto[] =\n"
386 	"#else\n"
387 	"short %sdgoto[] =\n"
388 	"#endif\n"
389 	"\t{%40d,", symbol_prefix, symbol_prefix, k);
390     save_column(start_symbol + 1, k);
391 
392     j = 10;
393     for (i = start_symbol + 2; i < nsyms; i++)
394     {
395 	if (j >= 10)
396 	{
397 	    if (!rflag) ++outline;
398 	    putc('\n', output_file);
399 	    j = 1;
400 	}
401 	else
402 	    ++j;
403 
404 	k = default_goto(i);
405 	fprintf(output_file, "%5d,", k);
406 	save_column(i, k);
407     }
408 
409     if (!rflag) outline += 2;
410     fprintf(output_file, "\n};\n");
411     FREE(state_count);
412 }
413 
414 int
415 default_goto(int symbol)
416 {
417     int i;
418     int m;
419     int n;
420     int default_state;
421     int max;
422 
423     m = goto_map[symbol];
424     n = goto_map[symbol + 1];
425 
426     if (m == n) return (0);
427 
428     for (i = 0; i < nstates; i++)
429 	state_count[i] = 0;
430 
431     for (i = m; i < n; i++)
432 	state_count[to_state[i]]++;
433 
434     max = 0;
435     default_state = 0;
436     for (i = 0; i < nstates; i++)
437     {
438 	if (state_count[i] > max)
439 	{
440 	    max = state_count[i];
441 	    default_state = i;
442 	}
443     }
444 
445     return (default_state);
446 }
447 
448 
449 
450 void
451 save_column(int symbol, int default_state)
452 {
453     int i;
454     int m;
455     int n;
456     short *sp;
457     short *sp1;
458     short *sp2;
459     int count;
460     int symno;
461 
462     m = goto_map[symbol];
463     n = goto_map[symbol + 1];
464 
465     count = 0;
466     for (i = m; i < n; i++)
467     {
468 	if (to_state[i] != default_state)
469 	    ++count;
470     }
471     if (count == 0) return;
472 
473     symno = symbol_value[symbol] + 2*nstates;
474 
475     froms[symno] = sp1 = sp = NEW2(count, short);
476     tos[symno] = sp2 = NEW2(count, short);
477 
478     for (i = m; i < n; i++)
479     {
480 	if (to_state[i] != default_state)
481 	{
482 	    *sp1++ = from_state[i];
483 	    *sp2++ = to_state[i];
484 	}
485     }
486 
487     tally[symno] = count;
488     width[symno] = sp1[-1] - sp[0] + 1;
489 }
490 
491 void
492 sort_actions(void)
493 {
494   int i;
495   int j;
496   int k;
497   int t;
498   int w;
499 
500   order = NEW2(nvectors, short);
501   nentries = 0;
502 
503   for (i = 0; i < nvectors; i++)
504     {
505       if (tally[i] > 0)
506 	{
507 	  t = tally[i];
508 	  w = width[i];
509 	  j = nentries - 1;
510 
511 	  while (j >= 0 && (width[order[j]] < w))
512 	    j--;
513 
514 	  while (j >= 0 && (width[order[j]] == w) && (tally[order[j]] < t))
515 	    j--;
516 
517 	  for (k = nentries - 1; k > j; k--)
518 	    order[k + 1] = order[k];
519 
520 	  order[j + 1] = i;
521 	  nentries++;
522 	}
523     }
524 }
525 
526 
527 void
528 pack_table(void)
529 {
530     int i;
531     int place;
532     int state;
533 
534     base = NEW2(nvectors, short);
535     pos = NEW2(nentries, short);
536 
537     maxtable = 1000;
538     table = NEW2(maxtable, short);
539     check = NEW2(maxtable, short);
540 
541     lowzero = 0;
542     high = 0;
543 
544     for (i = 0; i < maxtable; i++)
545 	check[i] = -1;
546 
547     for (i = 0; i < nentries; i++)
548     {
549 	state = matching_vector(i);
550 
551 	if (state < 0)
552 	    place = pack_vector(i);
553 	else
554 	    place = base[state];
555 
556 	pos[i] = place;
557 	base[order[i]] = place;
558     }
559 
560     for (i = 0; i < nvectors; i++)
561     {
562 	if (froms[i])
563 	    FREE(froms[i]);
564 	if (tos[i])
565 	    FREE(tos[i]);
566     }
567 
568     FREE(froms);
569     FREE(tos);
570     FREE(pos);
571 }
572 
573 
574 /*  The function matching_vector determines if the vector specified by	*/
575 /*  the input parameter matches a previously considered	vector.  The	*/
576 /*  test at the start of the function checks if the vector represents	*/
577 /*  a row of shifts over terminal symbols or a row of reductions, or a	*/
578 /*  column of shifts over a nonterminal symbol.  Berkeley Yacc does not	*/
579 /*  check if a column of shifts over a nonterminal symbols matches a	*/
580 /*  previously considered vector.  Because of the nature of LR parsing	*/
581 /*  tables, no two columns can match.  Therefore, the only possible	*/
582 /*  match would be between a row and a column.  Such matches are	*/
583 /*  unlikely.  Therefore, to save time, no attempt is made to see if a	*/
584 /*  column matches a previously considered vector.			*/
585 /*									*/
586 /*  Matching_vector is poorly designed.  The test could easily be made	*/
587 /*  faster.  Also, it depends on the vectors being in a specific	*/
588 /*  order.								*/
589 
590 int
591 matching_vector(int vector)
592 {
593     int i;
594     int j;
595     int k;
596     int t;
597     int w;
598     int match;
599     int prev;
600 
601     i = order[vector];
602     if (i >= 2*nstates)
603 	return (-1);
604 
605     t = tally[i];
606     w = width[i];
607 
608     for (prev = vector - 1; prev >= 0; prev--)
609     {
610 	j = order[prev];
611 	if (width[j] != w || tally[j] != t)
612 	    return (-1);
613 
614 	match = 1;
615 	for (k = 0; match && k < t; k++)
616 	{
617 	    if (tos[j][k] != tos[i][k] || froms[j][k] != froms[i][k])
618 		match = 0;
619 	}
620 
621 	if (match)
622 	    return (j);
623     }
624 
625     return (-1);
626 }
627 
628 
629 
630 int
631 pack_vector(int vector)
632 {
633     int i, j, k, l;
634     int t;
635     int loc;
636     int ok;
637     short *from;
638     short *to;
639     int newmax;
640 
641     i = order[vector];
642     t = tally[i];
643     assert(t);
644 
645     from = froms[i];
646     to = tos[i];
647 
648     j = lowzero - from[0];
649     for (k = 1; k < t; ++k)
650 	if (lowzero - from[k] > j)
651 	    j = lowzero - from[k];
652     for (;; ++j)
653     {
654 	if (j == 0)
655 	    continue;
656 	ok = 1;
657 	for (k = 0; ok && k < t; k++)
658 	{
659 	    loc = j + from[k];
660 	    if (loc >= maxtable)
661 	    {
662 		if (loc >= MAXTABLE)
663 		    fatal("maximum table size exceeded");
664 
665 		newmax = maxtable;
666 		do { newmax += 200; } while (newmax <= loc);
667 		table = (short *) REALLOC(table, newmax*sizeof(short));
668 		if (table == 0) no_space();
669 		check = (short *) REALLOC(check, newmax*sizeof(short));
670 		if (check == 0) no_space();
671 		for (l  = maxtable; l < newmax; ++l)
672 		{
673 		    table[l] = 0;
674 		    check[l] = -1;
675 		}
676 		maxtable = newmax;
677 	    }
678 
679 	    if (check[loc] != -1)
680 		ok = 0;
681 	}
682 	for (k = 0; ok && k < vector; k++)
683 	{
684 	    if (pos[k] == j)
685 		ok = 0;
686 	}
687 	if (ok)
688 	{
689 	    for (k = 0; k < t; k++)
690 	    {
691 		loc = j + from[k];
692 		table[loc] = to[k];
693 		check[loc] = from[k];
694 		if (loc > high) high = loc;
695 	    }
696 
697 	    while (check[lowzero] != -1)
698 		++lowzero;
699 
700 	    return (j);
701 	}
702     }
703 }
704 
705 
706 
707 void
708 output_base(void)
709 {
710     int i, j;
711 
712     fprintf(output_file,
713 	"#if defined(__cplusplus) || defined(__STDC__)\n"
714 	"const short %ssindex[] =\n"
715 	"#else\n"
716 	"short %ssindex[] =\n"
717 	"#endif\n"
718 	"\t{%39d,", symbol_prefix, symbol_prefix, base[0]);
719 
720     j = 10;
721     for (i = 1; i < nstates; i++)
722     {
723 	if (j >= 10)
724 	{
725 	    if (!rflag) ++outline;
726 	    putc('\n', output_file);
727 	    j = 1;
728 	}
729 	else
730 	    ++j;
731 
732 	fprintf(output_file, "%5d,", base[i]);
733     }
734 
735     if (!rflag) outline += 2;
736     fprintf(output_file,
737 	"};\n"
738 	"#if defined(__cplusplus) || defined(__STDC__)\n"
739 	"const short %srindex[] =\n"
740 	"#else\n"
741 	"short %srindex[] =\n"
742 	"#endif\n"
743 	"\t{%39d,", symbol_prefix, symbol_prefix, base[nstates]);
744 
745     j = 10;
746     for (i = nstates + 1; i < 2*nstates; i++)
747     {
748 	if (j >= 10)
749 	{
750 	    if (!rflag) ++outline;
751 	    putc('\n', output_file);
752 	    j = 1;
753 	}
754 	else
755 	    ++j;
756 
757 	fprintf(output_file, "%5d,", base[i]);
758     }
759 
760     if (!rflag) outline += 2;
761     fprintf(output_file,
762 	"};\n"
763 	"#if defined(__cplusplus) || defined(__STDC__)\n"
764 	"const short %sgindex[] =\n"
765 	"#else\n"
766 	"short %sgindex[] =\n"
767 	"#endif\n"
768 	"\t{%39d,", symbol_prefix, symbol_prefix, base[2*nstates]);
769 
770     j = 10;
771     for (i = 2*nstates + 1; i < nvectors - 1; i++)
772     {
773 	if (j >= 10)
774 	{
775 	    if (!rflag) ++outline;
776 	    putc('\n', output_file);
777 	    j = 1;
778 	}
779 	else
780 	    ++j;
781 
782 	fprintf(output_file, "%5d,", base[i]);
783     }
784 
785     if (!rflag) outline += 2;
786     fprintf(output_file, "\n};\n");
787     FREE(base);
788 }
789 
790 
791 void
792 output_table(void)
793 {
794     int i;
795     int j;
796 
797     ++outline;
798     fprintf(code_file, "#define YYTABLESIZE %d\n", high);
799     fprintf(output_file,
800 	"#if defined(__cplusplus) || defined(__STDC__)\n"
801 	"const short %stable[] =\n"
802 	"#else\n"
803 	"short %stable[] =\n"
804 	"#endif\n"
805 	"\t{%40d,", symbol_prefix, symbol_prefix, table[0]);
806 
807     j = 10;
808     for (i = 1; i <= high; i++)
809     {
810 	if (j >= 10)
811 	{
812 	    if (!rflag) ++outline;
813 	    putc('\n', output_file);
814 	    j = 1;
815 	}
816 	else
817 	    ++j;
818 
819 	fprintf(output_file, "%5d,", table[i]);
820     }
821 
822     if (!rflag) outline += 2;
823     fprintf(output_file, "\n};\n");
824     FREE(table);
825 }
826 
827 
828 void
829 output_check(void)
830 {
831     int i;
832     int j;
833 
834     fprintf(output_file,
835 	"#if defined(__cplusplus) || defined(__STDC__)\n"
836 	"const short %scheck[] =\n"
837 	"#else\n"
838 	"short %scheck[] =\n"
839 	"#endif\n"
840 	"\t{%40d,", symbol_prefix, symbol_prefix, check[0]);
841 
842     j = 10;
843     for (i = 1; i <= high; i++)
844     {
845 	if (j >= 10)
846 	{
847 	    if (!rflag) ++outline;
848 	    putc('\n', output_file);
849 	    j = 1;
850 	}
851 	else
852 	    ++j;
853 
854 	fprintf(output_file, "%5d,", check[i]);
855     }
856 
857     if (!rflag) outline += 2;
858     fprintf(output_file, "\n};\n");
859     FREE(check);
860 }
861 
862 
863 int
864 is_C_identifier(char *name)
865 {
866     char *s;
867     int c;
868 
869     s = name;
870     c = *s;
871     if (c == '"')
872     {
873 	c = *++s;
874 	if (!isalpha(c) && c != '_' && c != '$')
875 	    return (0);
876 	while ((c = *++s) != '"')
877 	{
878 	    if (!isalnum(c) && c != '_' && c != '$')
879 		return (0);
880 	}
881 	return (1);
882     }
883 
884     if (!isalpha(c) && c != '_' && c != '$')
885 	return (0);
886     while ((c = *++s))
887     {
888 	if (!isalnum(c) && c != '_' && c != '$')
889 	    return (0);
890     }
891     return (1);
892 }
893 
894 
895 void
896 output_defines(void)
897 {
898     int c, i;
899     char *s;
900 
901     for (i = 2; i < ntokens; ++i)
902     {
903 	s = symbol_name[i];
904 	if (is_C_identifier(s))
905 	{
906 	    fprintf(code_file, "#define ");
907 	    if (dflag) fprintf(defines_file, "#define ");
908 	    c = *s;
909 	    if (c == '"')
910 	    {
911 		while ((c = *++s) != '"')
912 		{
913 		    putc(c, code_file);
914 		    if (dflag) putc(c, defines_file);
915 		}
916 	    }
917 	    else
918 	    {
919 		do
920 		{
921 		    putc(c, code_file);
922 		    if (dflag) putc(c, defines_file);
923 		}
924 		while ((c = *++s));
925 	    }
926 	    ++outline;
927 	    fprintf(code_file, " %d\n", symbol_value[i]);
928 	    if (dflag) fprintf(defines_file, " %d\n", symbol_value[i]);
929 	}
930     }
931 
932     ++outline;
933     fprintf(code_file, "#define YYERRCODE %d\n", symbol_value[1]);
934 
935     if (dflag && unionized)
936     {
937 	fclose(union_file);
938 	union_file = fopen(union_file_name, "r");
939 	if (union_file == NULL) open_error(union_file_name);
940 	while ((c = getc(union_file)) != EOF)
941 	    putc(c, defines_file);
942 	fprintf(defines_file, " YYSTYPE;\n");
943 	fprintf(defines_file, "#endif /* YYSTYPE_DEFINED */\n");
944 	fprintf(defines_file, "extern YYSTYPE %slval;\n",
945 		symbol_prefix);
946     }
947 }
948 
949 
950 void
951 output_stored_text(void)
952 {
953     int c;
954     FILE *in, *out;
955 
956     fclose(text_file);
957     text_file = fopen(text_file_name, "r");
958     if (text_file == NULL)
959 	open_error(text_file_name);
960     in = text_file;
961     if ((c = getc(in)) == EOF)
962 	return;
963     out = code_file;
964     if (c ==  '\n')
965 	++outline;
966     putc(c, out);
967     while ((c = getc(in)) != EOF)
968     {
969 	if (c == '\n')
970 	    ++outline;
971 	putc(c, out);
972     }
973     if (!lflag)
974 	fprintf(out, line_format, ++outline + 1, code_file_name);
975 }
976 
977 
978 void
979 output_debug(void)
980 {
981     int i, j, k, max;
982     char **symnam, *s;
983 
984     ++outline;
985     fprintf(code_file, "#define YYFINAL %d\n", final_state);
986     outline += 3;
987     fprintf(code_file, "#ifndef YYDEBUG\n#define YYDEBUG %d\n#endif\n",
988 	    tflag);
989     if (rflag)
990 	fprintf(output_file, "#ifndef YYDEBUG\n#define YYDEBUG %d\n#endif\n",
991 		tflag);
992 
993     max = 0;
994     for (i = 2; i < ntokens; ++i)
995 	if (symbol_value[i] > max)
996 	    max = symbol_value[i];
997     ++outline;
998     fprintf(code_file, "#define YYMAXTOKEN %d\n", max);
999 
1000     symnam = (char **) MALLOC((max+1)*sizeof(char *));
1001     if (symnam == 0) no_space();
1002 
1003     /* Note that it is  not necessary to initialize the element		*/
1004     /* symnam[max].							*/
1005     for (i = 0; i < max; ++i)
1006 	symnam[i] = 0;
1007     for (i = ntokens - 1; i >= 2; --i)
1008 	symnam[symbol_value[i]] = symbol_name[i];
1009     symnam[0] = "end-of-file";
1010 
1011     if (!rflag) ++outline;
1012     fprintf(output_file,
1013 	"#if YYDEBUG\n"
1014 	"#if defined(__cplusplus) || defined(__STDC__)\n"
1015 	"const char * const %sname[] =\n"
1016 	"#else\n"
1017 	"char *%sname[] =\n"
1018 	"#endif\n"
1019 	"\t{", symbol_prefix, symbol_prefix);
1020     j = 80;
1021     for (i = 0; i <= max; ++i)
1022     {
1023 	if ((s = symnam[i]) != '\0')
1024 	{
1025 	    if (s[0] == '"')
1026 	    {
1027 		k = 7;
1028 		while (*++s != '"')
1029 		{
1030 		    ++k;
1031 		    if (*s == '\\')
1032 		    {
1033 			k += 2;
1034 			if (*++s == '\\')
1035 			    ++k;
1036 		    }
1037 		}
1038 		j += k;
1039 		if (j > 80)
1040 		{
1041 		    if (!rflag) ++outline;
1042 		    putc('\n', output_file);
1043 		    j = k;
1044 		}
1045 		fprintf(output_file, "\"\\\"");
1046 		s = symnam[i];
1047 		while (*++s != '"')
1048 		{
1049 		    if (*s == '\\')
1050 		    {
1051 			fprintf(output_file, "\\\\");
1052 			if (*++s == '\\')
1053 			    fprintf(output_file, "\\\\");
1054 			else
1055 			    putc(*s, output_file);
1056 		    }
1057 		    else
1058 			putc(*s, output_file);
1059 		}
1060 		fprintf(output_file, "\\\"\",");
1061 	    }
1062 	    else if (s[0] == '\'')
1063 	    {
1064 		if (s[1] == '"')
1065 		{
1066 		    j += 7;
1067 		    if (j > 80)
1068 		    {
1069 			if (!rflag) ++outline;
1070 			putc('\n', output_file);
1071 			j = 7;
1072 		    }
1073 		    fprintf(output_file, "\"'\\\"'\",");
1074 		}
1075 		else
1076 		{
1077 		    k = 5;
1078 		    while (*++s != '\'')
1079 		    {
1080 			++k;
1081 			if (*s == '\\')
1082 			{
1083 			    k += 2;
1084 			    if (*++s == '\\')
1085 				++k;
1086 			}
1087 		    }
1088 		    j += k;
1089 		    if (j > 80)
1090 		    {
1091 			if (!rflag) ++outline;
1092 			putc('\n', output_file);
1093 			j = k;
1094 		    }
1095 		    fprintf(output_file, "\"'");
1096 		    s = symnam[i];
1097 		    while (*++s != '\'')
1098 		    {
1099 			if (*s == '\\')
1100 			{
1101 			    fprintf(output_file, "\\\\");
1102 			    if (*++s == '\\')
1103 				fprintf(output_file, "\\\\");
1104 			    else
1105 				putc(*s, output_file);
1106 			}
1107 			else
1108 			    putc(*s, output_file);
1109 		    }
1110 		    fprintf(output_file, "'\",");
1111 		}
1112 	    }
1113 	    else
1114 	    {
1115 		k = strlen(s) + 3;
1116 		j += k;
1117 		if (j > 80)
1118 		{
1119 		    if (!rflag) ++outline;
1120 		    putc('\n', output_file);
1121 		    j = k;
1122 		}
1123 		putc('"', output_file);
1124 		do { putc(*s, output_file); } while (*++s);
1125 		fprintf(output_file, "\",");
1126 	    }
1127 	}
1128 	else
1129 	{
1130 	    j += 2;
1131 	    if (j > 80)
1132 	    {
1133 		if (!rflag) ++outline;
1134 		putc('\n', output_file);
1135 		j = 2;
1136 	    }
1137 	    fprintf(output_file, "0,");
1138 	}
1139     }
1140     if (!rflag) outline += 2;
1141     fprintf(output_file, "\n};\n");
1142     FREE(symnam);
1143 
1144     if (!rflag) ++outline;
1145     fprintf(output_file,
1146 	"#if defined(__cplusplus) || defined(__STDC__)\n"
1147 	"const char * const %srule[] =\n"
1148 	"#else\n"
1149 	"char *%srule[] =\n"
1150 	"#endif\n"
1151 	"\t{", symbol_prefix, symbol_prefix);
1152     for (i = 2; i < nrules; ++i)
1153     {
1154 	fprintf(output_file, "\"%s :", symbol_name[rlhs[i]]);
1155 	for (j = rrhs[i]; ritem[j] > 0; ++j)
1156 	{
1157 	    s = symbol_name[ritem[j]];
1158 	    if (s[0] == '"')
1159 	    {
1160 		fprintf(output_file, " \\\"");
1161 		while (*++s != '"')
1162 		{
1163 		    if (*s == '\\')
1164 		    {
1165 			if (s[1] == '\\')
1166 			    fprintf(output_file, "\\\\\\\\");
1167 			else
1168 			    fprintf(output_file, "\\\\%c", s[1]);
1169 			++s;
1170 		    }
1171 		    else
1172 			putc(*s, output_file);
1173 		}
1174 		fprintf(output_file, "\\\"");
1175 	    }
1176 	    else if (s[0] == '\'')
1177 	    {
1178 		if (s[1] == '"')
1179 		    fprintf(output_file, " '\\\"'");
1180 		else if (s[1] == '\\')
1181 		{
1182 		    if (s[2] == '\\')
1183 			fprintf(output_file, " '\\\\\\\\");
1184 		    else
1185 			fprintf(output_file, " '\\\\%c", s[2]);
1186 		    s += 2;
1187 		    while (*++s != '\'')
1188 			putc(*s, output_file);
1189 		    putc('\'', output_file);
1190 		}
1191 		else
1192 		    fprintf(output_file, " '%c'", s[1]);
1193 	    }
1194 	    else
1195 		fprintf(output_file, " %s", s);
1196 	}
1197 	if (!rflag) ++outline;
1198 	fprintf(output_file, "\",\n");
1199     }
1200 
1201     if (!rflag) outline += 2;
1202     fprintf(output_file, "};\n#endif\n");
1203 }
1204 
1205 
1206 void
1207 output_stype(void)
1208 {
1209     if (!unionized && ntags == 0)
1210     {
1211 	outline += 3;
1212 	fprintf(code_file, "#ifndef YYSTYPE\ntypedef int YYSTYPE;\n#endif\n");
1213     }
1214 }
1215 
1216 
1217 void
1218 output_trailing_text(void)
1219 {
1220     int c, last;
1221     FILE *in, *out;
1222 
1223     if (line == 0)
1224 	return;
1225 
1226     in = input_file;
1227     out = code_file;
1228     c = *cptr;
1229     if (c == '\n')
1230     {
1231 	++lineno;
1232 	if ((c = getc(in)) == EOF)
1233 	    return;
1234 	if (!lflag)
1235 	{
1236 	    ++outline;
1237 	    fprintf(out, line_format, lineno, input_file_name);
1238 	}
1239 	if (c == '\n')
1240 	    ++outline;
1241 	putc(c, out);
1242 	last = c;
1243     }
1244     else
1245     {
1246 	if (!lflag)
1247 	{
1248 	    ++outline;
1249 	    fprintf(out, line_format, lineno, input_file_name);
1250 	}
1251 	do { putc(c, out); } while ((c = *++cptr) != '\n');
1252 	++outline;
1253 	putc('\n', out);
1254 	last = '\n';
1255     }
1256 
1257     while ((c = getc(in)) != EOF)
1258     {
1259 	if (c == '\n')
1260 	    ++outline;
1261 	putc(c, out);
1262 	last = c;
1263     }
1264 
1265     if (last != '\n')
1266     {
1267 	++outline;
1268 	putc('\n', out);
1269     }
1270     if (!lflag)
1271 	fprintf(out, line_format, ++outline + 1, code_file_name);
1272 }
1273 
1274 
1275 void
1276 output_semantic_actions(void)
1277 {
1278     int c, last;
1279     FILE *out;
1280 
1281     fclose(action_file);
1282     action_file = fopen(action_file_name, "r");
1283     if (action_file == NULL)
1284 	open_error(action_file_name);
1285 
1286     if ((c = getc(action_file)) == EOF)
1287 	return;
1288 
1289     out = code_file;
1290     last = c;
1291     if (c == '\n')
1292 	++outline;
1293     putc(c, out);
1294     while ((c = getc(action_file)) != EOF)
1295     {
1296 	if (c == '\n')
1297 	    ++outline;
1298 	putc(c, out);
1299 	last = c;
1300     }
1301 
1302     if (last != '\n')
1303     {
1304 	++outline;
1305 	putc('\n', out);
1306     }
1307 
1308     if (!lflag)
1309 	fprintf(out, line_format, ++outline + 1, code_file_name);
1310 }
1311 
1312 
1313 void
1314 free_itemsets(void)
1315 {
1316     core *cp, *next;
1317 
1318     FREE(state_table);
1319     for (cp = first_state; cp; cp = next)
1320     {
1321 	next = cp->next;
1322 	FREE(cp);
1323     }
1324 }
1325 
1326 
1327 void
1328 free_shifts(void)
1329 {
1330     shifts *sp, *next;
1331 
1332     FREE(shift_table);
1333     for (sp = first_shift; sp; sp = next)
1334     {
1335 	next = sp->next;
1336 	FREE(sp);
1337     }
1338 }
1339 
1340 
1341 
1342 void
1343 free_reductions(void)
1344 {
1345     reductions *rp, *next;
1346 
1347     FREE(reduction_table);
1348     for (rp = first_reduction; rp; rp = next)
1349     {
1350 	next = rp->next;
1351 	FREE(rp);
1352     }
1353 }
1354