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