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