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