GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/yacc/reader.c Lines: 741 1103 67.2 %
Date: 2017-11-13 Branches: 380 811 46.9 %

Line Branch Exec Source
1
/* $OpenBSD: reader.c,v 1.34 2017/05/25 20:11:03 tedu Exp $	 */
2
/* $NetBSD: reader.c,v 1.5 1996/03/19 03:21:43 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 <limits.h>
37
#include "defs.h"
38
39
/* The line size must be a positive integer.  One hundred was chosen	 */
40
/* because few lines in Yacc input grammars exceed 100 characters.	 */
41
/* Note that if a line exceeds LINESIZE characters, the line buffer	 */
42
/* will be expanded to accommodate it.					 */
43
44
#define LINESIZE 100
45
46
char *cache;
47
int cinc, cache_size;
48
49
int ntags, tagmax;
50
char **tag_table;
51
52
char saw_eof, unionized;
53
char *cptr, *line;
54
int linesize;
55
56
bucket *goal;
57
int prec;
58
int gensym;
59
char last_was_action;
60
61
int maxitems;
62
bucket **pitem;
63
64
int maxrules;
65
bucket **plhs;
66
67
int name_pool_size;
68
char *name_pool;
69
70
void cachec(int);
71
void get_line(void);
72
char *dup_line(void);
73
void skip_comment(void);
74
int nextc(void);
75
int keyword(void);
76
void copy_ident(void);
77
void copy_text(void);
78
void copy_union(void);
79
bucket *get_literal(void);
80
int is_reserved(char *);
81
bucket *get_name(void);
82
int get_number(void);
83
char *get_tag(void);
84
void declare_tokens(int);
85
void declare_types(void);
86
void declare_start(void);
87
void handle_expect(void);
88
void read_declarations(void);
89
void initialize_grammar(void);
90
void expand_items(void);
91
void expand_rules(void);
92
void advance_to_start(void);
93
void start_rule(bucket *, int);
94
void end_rule(void);
95
void insert_empty_rule(void);
96
void add_symbol(void);
97
void copy_action(void);
98
int mark_symbol(void);
99
void read_grammar(void);
100
void free_tags(void);
101
void pack_names(void);
102
void check_symbols(void);
103
void pack_symbols(void);
104
void pack_grammar(void);
105
void print_grammar(void);
106
107
char line_format[] = "#line %d \"%s\"\n";
108
109
void
110
cachec(int c)
111
{
112
47176
	assert(cinc >= 0);
113
23588
	if (cinc >= cache_size) {
114
		cache_size += 256;
115
		cache = realloc(cache, cache_size);
116
		if (cache == NULL)
117
			no_space();
118
	}
119
23588
	cache[cinc] = c;
120
23588
	++cinc;
121
23588
}
122
123
124
void
125
get_line(void)
126
{
127
14154
	FILE *f = input_file;
128
	int c, i;
129
130


35385
	if (saw_eof || (c = getc(f)) == EOF) {
131
		if (line) {
132
			free(line);
133
			line = 0;
134
		}
135
		cptr = 0;
136
		saw_eof = 1;
137
		return;
138
	}
139
7077
	if (line == NULL || linesize != (LINESIZE + 1)) {
140
11
		free(line);
141
11
		linesize = LINESIZE + 1;
142
11
		line = malloc(linesize);
143
11
		if (line == NULL)
144
			no_space();
145
	}
146
	i = 0;
147
7077
	++lineno;
148
151933
	for (;;) {
149
151933
		line[i] = c;
150
151933
		if (c == '\n') {
151
7077
			cptr = line;
152
7077
			return;
153
		}
154
144856
		if (++i >= linesize) {
155
2
			linesize += LINESIZE;
156
2
			line = realloc(line, linesize);
157
2
			if (line == NULL)
158
				no_space();
159
		}
160

579424
		c = getc(f);
161
144856
		if (c == EOF) {
162
			line[i] = '\n';
163
			saw_eof = 1;
164
			cptr = line;
165
			return;
166
		}
167
	}
168
7077
}
169
170
171
char *
172
dup_line(void)
173
{
174
	char *p, *s, *t;
175
176
3332
	if (line == NULL)
177
		return (0);
178
	s = line;
179
96854
	while (*s != '\n')
180
46761
		++s;
181
1666
	p = malloc(s - line + 1);
182
1666
	if (p == NULL)
183
		no_space();
184
185
1666
	s = line;
186
	t = p;
187
50093
	while ((*t++ = *s++) != '\n')
188
46761
		continue;
189
1666
	return (p);
190
1666
}
191
192
193
void
194
skip_comment(void)
195
{
196
	char *s;
197
162
	int st_lineno = lineno;
198
81
	char *st_line = dup_line();
199
81
	char *st_cptr = st_line + (cptr - line);
200
201
81
	s = cptr + 2;
202
13867
	for (;;) {
203

14192
		if (*s == '*' && s[1] == '/') {
204
81
			cptr = s + 2;
205
81
			free(st_line);
206
			return;
207
		}
208
13786
		if (*s == '\n') {
209
266
			get_line();
210
266
			if (line == NULL)
211
				unterminated_comment(st_lineno, st_line, st_cptr);
212
266
			s = cptr;
213
266
		} else
214
13520
			++s;
215
	}
216
81
}
217
218
219
int
220
nextc(void)
221
{
222
	char *s;
223
224
16682
	if (line == NULL) {
225
9
		get_line();
226
9
		if (line == NULL)
227
			return (EOF);
228
	}
229
8341
	s = cptr;
230
18140
	for (;;) {
231


18140
		switch (*s) {
232
		case '\n':
233
2159
			get_line();
234
2159
			if (line == NULL)
235
				return (EOF);
236
2159
			s = cptr;
237
2159
			break;
238
239
		case ' ':
240
		case '\t':
241
		case '\f':
242
		case '\r':
243
		case '\v':
244
		case ',':
245
		case ';':
246
7559
			++s;
247
7559
			break;
248
249
		case '\\':
250
			cptr = s;
251
			return ('%');
252
253
		case '/':
254
81
			if (s[1] == '*') {
255
81
				cptr = s;
256
81
				skip_comment();
257
81
				s = cptr;
258
81
				break;
259
			} else if (s[1] == '/') {
260
				get_line();
261
				if (line == NULL)
262
					return (EOF);
263
				s = cptr;
264
				break;
265
			}
266
			/* fall through */
267
268
		default:
269
8341
			cptr = s;
270
8341
			return ((unsigned char) *s);
271
		}
272
	}
273
8341
}
274
275
276
int
277
keyword(void)
278
{
279
	int c;
280
362
	char *t_cptr = cptr;
281
282
181
	c = (unsigned char) *++cptr;
283
181
	if (isalpha(c)) {
284
163
		cinc = 0;
285
923
		for (;;) {
286
923
			if (isalpha(c)) {
287
760
				if (isupper(c))
288
					c = tolower(c);
289
760
				cachec(c);
290
923
			} else if (isdigit(c) || c == '_' || c == '.' || c == '$')
291
				cachec(c);
292
			else
293
				break;
294
760
			c = (unsigned char) *++cptr;
295
		}
296
163
		cachec(NUL);
297
298

268
		if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0)
299
58
			return (TOKEN);
300
105
		if (strcmp(cache, "type") == 0)
301
57
			return (TYPE);
302
48
		if (strcmp(cache, "left") == 0)
303
22
			return (LEFT);
304
26
		if (strcmp(cache, "right") == 0)
305
2
			return (RIGHT);
306

40
		if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0)
307
8
			return (NONASSOC);
308
16
		if (strcmp(cache, "start") == 0)
309
7
			return (START);
310
9
		if (strcmp(cache, "union") == 0)
311
9
			return (UNION);
312
		if (strcmp(cache, "ident") == 0)
313
			return (IDENT);
314
		if (strcmp(cache, "expect") == 0)
315
			return (EXPECT);
316
	} else {
317
18
		++cptr;
318
18
		if (c == '{')
319
9
			return (TEXT);
320
9
		if (c == '%' || c == '\\')
321
9
			return (MARK);
322
		if (c == '<')
323
			return (LEFT);
324
		if (c == '>')
325
			return (RIGHT);
326
		if (c == '0')
327
			return (TOKEN);
328
		if (c == '2')
329
			return (NONASSOC);
330
	}
331
	syntax_error(lineno, line, t_cptr);
332
	/* NOTREACHED */
333
	return (0);
334
181
}
335
336
337
void
338
copy_ident(void)
339
{
340
	int c;
341
	FILE *f = output_file;
342
343
	c = nextc();
344
	if (c == EOF)
345
		unexpected_EOF();
346
	if (c != '"')
347
		syntax_error(lineno, line, cptr);
348
	++outline;
349
	fprintf(f, "#ident \"");
350
	for (;;) {
351
		c = (unsigned char) *++cptr;
352
		if (c == '\n') {
353
			fprintf(f, "\"\n");
354
			return;
355
		}
356
		putc(c, f);
357
		if (c == '"') {
358
			putc('\n', f);
359
			++cptr;
360
			return;
361
		}
362
	}
363
}
364
365
366
void
367
copy_text(void)
368
{
369
	int c;
370
	int quote;
371
18
	FILE *f = text_file;
372
	int need_newline = 0;
373
9
	int t_lineno = lineno;
374
9
	char *t_line = dup_line();
375
9
	char *t_cptr = t_line + (cptr - line - 2);
376
377
9
	if (*cptr == '\n') {
378
9
		get_line();
379
9
		if (line == NULL)
380
			unterminated_text(t_lineno, t_line, t_cptr);
381
	}
382
18
	if (!lflag)
383
9
		fprintf(f, line_format, lineno, input_file_name);
384
385
loop:
386
7308
	c = (unsigned char) *cptr++;
387

7308
	switch (c) {
388
	case '\n':
389
next_line:
390
870
		putc('\n', f);
391
		need_newline = 0;
392
435
		get_line();
393
435
		if (line)
394
435
			goto loop;
395
		unterminated_text(t_lineno, t_line, t_cptr);
396
397
	case '\'':
398
	case '"': {
399
22
		int s_lineno = lineno;
400
22
		char *s_line = dup_line();
401
22
		char *s_cptr = s_line + (cptr - line - 1);
402
403
		quote = c;
404
44
		putc(c, f);
405
209
		for (;;) {
406
209
			c = (unsigned char) *cptr++;
407
418
			putc(c, f);
408
209
			if (c == quote) {
409
				need_newline = 1;
410
22
				free(s_line);
411
				goto loop;
412
			}
413
187
			if (c == '\n')
414
				unterminated_string(s_lineno, s_line, s_cptr);
415
187
			if (c == '\\') {
416
				c = (unsigned char) *cptr++;
417
				putc(c, f);
418
				if (c == '\n') {
419
					get_line();
420
					if (line == NULL)
421
						unterminated_string(s_lineno, s_line, s_cptr);
422
				}
423
			}
424
		}
425
	}
426
427
	case '/':
428
98
		putc(c, f);
429
		need_newline = 1;
430
49
		c = (unsigned char) *cptr;
431
49
		if (c == '/') {
432
			putc('*', f);
433
			while ((c = (unsigned char) *++cptr) != '\n') {
434
				if (c == '*' && cptr[1] == '/')
435
					fprintf(f, "* ");
436
				else
437
					putc(c, f);
438
			}
439
			fprintf(f, "*/");
440
			goto next_line;
441
		}
442
49
		if (c == '*') {
443
6
			int c_lineno = lineno;
444
6
			char *c_line = dup_line();
445
6
			char *c_cptr = c_line + (cptr - line - 1);
446
447
12
			putc('*', f);
448
6
			++cptr;
449
2568
			for (;;) {
450
2568
				c = (unsigned char) *cptr++;
451
5136
				putc(c, f);
452

2612
				if (c == '*' && *cptr == '/') {
453
12
					putc('/', f);
454
6
					++cptr;
455
6
					free(c_line);
456
					goto loop;
457
				}
458
2562
				if (c == '\n') {
459
40
					get_line();
460
40
					if (line == NULL)
461
						unterminated_comment(c_lineno, c_line, c_cptr);
462
				}
463
			}
464
		}
465
		need_newline = 1;
466
43
		goto loop;
467
468
	case '%':
469
	case '\\':
470
13
		if (*cptr == '}') {
471
9
			if (need_newline)
472
				putc('\n', f);
473
9
			++cptr;
474
9
			free(t_line);
475
			return;
476
		}
477
		/* fall through */
478
479
	default:
480
13578
		putc(c, f);
481
		need_newline = 1;
482
6789
		goto loop;
483
	}
484
9
}
485
486
487
void
488
copy_union(void)
489
{
490
	int c, quote, depth;
491
18
	int u_lineno = lineno;
492
9
	char *u_line = dup_line();
493
9
	char *u_cptr = u_line + (cptr - line - 6);
494
495
9
	if (unionized)
496
		over_unionized(cptr - 6);
497
9
	unionized = 1;
498
499
9
	if (!lflag)
500
9
		fprintf(text_file, line_format, lineno, input_file_name);
501
502
9
	fprintf(text_file, "#ifndef YYSTYPE_DEFINED\n");
503
9
	fprintf(text_file, "#define YYSTYPE_DEFINED\n");
504
9
	fprintf(text_file, "typedef union");
505
9
	if (dflag) {
506
4
		fprintf(union_file, "#ifndef YYSTYPE_DEFINED\n");
507
4
		fprintf(union_file, "#define YYSTYPE_DEFINED\n");
508
4
		fprintf(union_file, "typedef union");
509
4
	}
510
511
9
	depth = 0;
512
loop:
513
660
	c = (unsigned char) *cptr++;
514
1320
	putc(c, text_file);
515
660
	if (dflag)
516
980
		putc(c, union_file);
517

660
	switch (c) {
518
	case '\n':
519
next_line:
520
54
		get_line();
521
54
		if (line == NULL)
522
			unterminated_union(u_lineno, u_line, u_cptr);
523
54
		goto loop;
524
525
	case '{':
526
11
		++depth;
527
11
		goto loop;
528
529
	case '}':
530
11
		if (--depth == 0) {
531
9
			fprintf(text_file, " YYSTYPE;\n");
532
9
			fprintf(text_file, "#endif /* YYSTYPE_DEFINED */\n");
533
9
			free(u_line);
534
			return;
535
		}
536
2
		goto loop;
537
538
	case '\'':
539
	case '"': {
540
		int s_lineno = lineno;
541
		char *s_line = dup_line();
542
		char *s_cptr = s_line + (cptr - line - 1);
543
544
		quote = c;
545
		for (;;) {
546
			c = (unsigned char) *cptr++;
547
			putc(c, text_file);
548
			if (dflag)
549
				putc(c, union_file);
550
			if (c == quote) {
551
				free(s_line);
552
				goto loop;
553
			}
554
			if (c == '\n')
555
				unterminated_string(s_lineno, s_line, s_cptr);
556
			if (c == '\\') {
557
				c = (unsigned char) *cptr++;
558
				putc(c, text_file);
559
				if (dflag)
560
					putc(c, union_file);
561
				if (c == '\n') {
562
					get_line();
563
					if (line == NULL)
564
						unterminated_string(s_lineno,
565
						    s_line, s_cptr);
566
				}
567
			}
568
		}
569
	}
570
571
	case '/':
572
		c = (unsigned char) *cptr;
573
		if (c == '/') {
574
			putc('*', text_file);
575
			if (dflag)
576
				putc('*', union_file);
577
			while ((c = (unsigned char) *++cptr) != '\n') {
578
				if (c == '*' && cptr[1] == '/') {
579
					fprintf(text_file, "* ");
580
					if (dflag)
581
						fprintf(union_file, "* ");
582
				} else {
583
					putc(c, text_file);
584
					if (dflag)
585
						putc(c, union_file);
586
				}
587
			}
588
			fprintf(text_file, "*/\n");
589
			if (dflag)
590
				fprintf(union_file, "*/\n");
591
			goto next_line;
592
		}
593
		if (c == '*') {
594
			int c_lineno = lineno;
595
			char *c_line = dup_line();
596
			char *c_cptr = c_line + (cptr - line - 1);
597
598
			putc('*', text_file);
599
			if (dflag)
600
				putc('*', union_file);
601
			++cptr;
602
			for (;;) {
603
				c = (unsigned char) *cptr++;
604
				putc(c, text_file);
605
				if (dflag)
606
					putc(c, union_file);
607
				if (c == '*' && *cptr == '/') {
608
					putc('/', text_file);
609
					if (dflag)
610
						putc('/', union_file);
611
					++cptr;
612
					free(c_line);
613
					goto loop;
614
				}
615
				if (c == '\n') {
616
					get_line();
617
					if (line == NULL)
618
						unterminated_comment(c_lineno,
619
						    c_line, c_cptr);
620
				}
621
			}
622
		}
623
		goto loop;
624
625
	default:
626
584
		goto loop;
627
	}
628
9
}
629
630
631
bucket *
632
get_literal(void)
633
{
634
	int c, quote, i, n;
635
140
	char *s;
636
	bucket *bp;
637
70
	int s_lineno = lineno;
638
70
	char *s_line = dup_line();
639
70
	char *s_cptr = s_line + (cptr - line);
640
641
70
	quote = (unsigned char) *cptr++;
642
70
	cinc = 0;
643
140
	for (;;) {
644
140
		c = (unsigned char) *cptr++;
645
140
		if (c == quote)
646
			break;
647
70
		if (c == '\n')
648
			unterminated_string(s_lineno, s_line, s_cptr);
649
70
		if (c == '\\') {
650
			char *c_cptr = cptr - 1;
651
			unsigned long ulval;
652
653
			c = (unsigned char) *cptr++;
654
			switch (c) {
655
			case '\n':
656
				get_line();
657
				if (line == NULL)
658
					unterminated_string(s_lineno, s_line,
659
					    s_cptr);
660
				continue;
661
662
			case '0':
663
			case '1':
664
			case '2':
665
			case '3':
666
			case '4':
667
			case '5':
668
			case '6':
669
			case '7':
670
				ulval = strtoul(cptr - 1, &s, 8);
671
				if (s == cptr - 1 || ulval > MAXCHAR)
672
					illegal_character(c_cptr);
673
				c = (int) ulval;
674
				cptr = s;
675
				break;
676
677
			case 'x':
678
				ulval = strtoul(cptr, &s, 16);
679
				if (s == cptr || ulval > MAXCHAR)
680
					illegal_character(c_cptr);
681
				c = (int) ulval;
682
				cptr = s;
683
				break;
684
685
			case 'a':
686
				c = 7;
687
				break;
688
			case 'b':
689
				c = '\b';
690
				break;
691
			case 'f':
692
				c = '\f';
693
				break;
694
			case 'n':
695
				c = '\n';
696
				break;
697
			case 'r':
698
				c = '\r';
699
				break;
700
			case 't':
701
				c = '\t';
702
				break;
703
			case 'v':
704
				c = '\v';
705
				break;
706
			}
707
		}
708
70
		cachec(c);
709
	}
710
70
	free(s_line);
711
712
70
	n = cinc;
713
70
	s = malloc(n);
714
70
	if (s == NULL)
715
		no_space();
716
717
70
	memcpy(s, cache, n);
718
719
70
	cinc = 0;
720
70
	if (n == 1)
721
70
		cachec('\'');
722
	else
723
		cachec('"');
724
725
280
	for (i = 0; i < n; ++i) {
726
70
		c = ((unsigned char *) s)[i];
727

140
		if (c == '\\' || c == cache[0]) {
728
			cachec('\\');
729
			cachec(c);
730
70
		} else if (isprint(c))
731
70
			cachec(c);
732
		else {
733
			cachec('\\');
734
			switch (c) {
735
			case 7:
736
				cachec('a');
737
				break;
738
			case '\b':
739
				cachec('b');
740
				break;
741
			case '\f':
742
				cachec('f');
743
				break;
744
			case '\n':
745
				cachec('n');
746
				break;
747
			case '\r':
748
				cachec('r');
749
				break;
750
			case '\t':
751
				cachec('t');
752
				break;
753
			case '\v':
754
				cachec('v');
755
				break;
756
			default:
757
				cachec(((c >> 6) & 7) + '0');
758
				cachec(((c >> 3) & 7) + '0');
759
				cachec((c & 7) + '0');
760
				break;
761
			}
762
		}
763
	}
764
765
70
	if (n == 1)
766
70
		cachec('\'');
767
	else
768
		cachec('"');
769
770
70
	cachec(NUL);
771
70
	bp = lookup(cache);
772
70
	bp->class = TERM;
773

140
	if (n == 1 && bp->value == UNDEFINED)
774
30
		bp->value = *(unsigned char *) s;
775
70
	free(s);
776
777
70
	return (bp);
778
70
}
779
780
781
int
782
is_reserved(char *name)
783
{
784
	char *s;
785
786

10332
	if (strcmp(name, ".") == 0 ||
787
3444
	    strcmp(name, "$accept") == 0 ||
788
3444
	    strcmp(name, "$end") == 0)
789
		return (1);
790
791

3444
	if (name[0] == '$' && name[1] == '$' && isdigit((unsigned char) name[2])) {
792
		s = name + 3;
793
		while (isdigit((unsigned char) *s))
794
			++s;
795
		if (*s == NUL)
796
			return (1);
797
	}
798
3444
	return (0);
799
3444
}
800
801
802
bucket *
803
get_name(void)
804
{
805
	int c;
806
807
6888
	cinc = 0;
808
44002
	for (c = (unsigned char) *cptr; IS_IDENT(c); c = (unsigned char) *++cptr)
809
18557
		cachec(c);
810
3444
	cachec(NUL);
811
812
3444
	if (is_reserved(cache))
813
		used_reserved(cache);
814
815
3444
	return (lookup(cache));
816
}
817
818
819
int
820
get_number(void)
821
{
822
	unsigned long ul;
823
3944
	char *p;
824
825
1972
	ul = strtoul(cptr, &p, 10);
826
1972
	if (ul > INT_MAX)
827
		syntax_error(lineno, line, cptr);
828
1972
	cptr = p;
829
3944
	return (ul);
830
1972
}
831
832
833
char *
834
get_tag(void)
835
{
836
	int c, i;
837
	char *s;
838
196
	int t_lineno = lineno;
839
98
	char *t_line = dup_line();
840
98
	char *t_cptr = t_line + (cptr - line);
841
842
98
	++cptr;
843
98
	c = nextc();
844
98
	if (c == EOF)
845
		unexpected_EOF();
846
98
	if (!isalpha(c) && c != '_' && c != '$')
847
		illegal_tag(t_lineno, t_line, t_cptr);
848
849
98
	cinc = 0;
850
98
	do {
851
216
		cachec(c);
852
216
		c = (unsigned char) *++cptr;
853

314
	} while (IS_IDENT(c));
854
98
	cachec(NUL);
855
856
98
	c = nextc();
857
98
	if (c == EOF)
858
		unexpected_EOF();
859
98
	if (c != '>')
860
		illegal_tag(t_lineno, t_line, t_cptr);
861
98
	free(t_line);
862
98
	++cptr;
863
864
388
	for (i = 0; i < ntags; ++i) {
865
159
		if (strcmp(cache, tag_table[i]) == 0)
866
63
			return (tag_table[i]);
867
	}
868
869
35
	if (ntags >= tagmax) {
870
9
		tagmax += 16;
871
9
		tag_table = reallocarray(tag_table, tagmax, sizeof(char *));
872
9
		if (tag_table == NULL)
873
			no_space();
874
	}
875
35
	s = malloc(cinc);
876
35
	if (s == NULL)
877
		no_space();
878
35
	strlcpy(s, cache, cinc);
879
35
	tag_table[ntags] = s;
880
35
	++ntags;
881
35
	return (s);
882
98
}
883
884
885
void
886
declare_tokens(int assoc)
887
{
888
	int c;
889
	bucket *bp;
890
	int value;
891
	char *tag = 0;
892
893
180
	if (assoc != TOKEN)
894
32
		++prec;
895
896
90
	c = nextc();
897
90
	if (c == EOF)
898
		unexpected_EOF();
899
90
	if (c == '<') {
900
15
		tag = get_tag();
901
15
		c = nextc();
902
15
		if (c == EOF)
903
			unexpected_EOF();
904
	}
905
675
	for (;;) {
906
675
		if (isalpha(c) || c == '_' || c == '.' || c == '$')
907
571
			bp = get_name();
908
104
		else if (c == '\'' || c == '"')
909
14
			bp = get_literal();
910
		else
911
			return;
912
913
585
		if (bp == goal)
914
			tokenized_start(bp->name);
915
585
		bp->class = TERM;
916
917
585
		if (tag) {
918

15
			if (bp->tag && tag != bp->tag)
919
				retyped_warning(bp->name);
920
15
			bp->tag = tag;
921
15
		}
922
585
		if (assoc != TOKEN) {
923

66
			if (bp->prec && prec != bp->prec)
924
				reprec_warning(bp->name);
925
66
			bp->assoc = assoc;
926
66
			bp->prec = prec;
927
66
		}
928
585
		c = nextc();
929
585
		if (c == EOF)
930
			unexpected_EOF();
931
585
		if (isdigit(c)) {
932
			value = get_number();
933
			if (bp->value != UNDEFINED && value != bp->value)
934
				revalued_warning(bp->name);
935
			bp->value = value;
936
			c = nextc();
937
			if (c == EOF)
938
				unexpected_EOF();
939
		}
940
	}
941
90
}
942
943
944
/*
945
 * %expect requires special handling as it really isn't part of the yacc
946
 * grammar only a flag for yacc proper.
947
 */
948
static void
949
declare_expect(int assoc)
950
{
951
	int c;
952
953
	if (assoc != EXPECT)
954
		++prec;
955
956
	/*
957
         * Stay away from nextc - doesn't detect EOL and will read to EOF.
958
         */
959
	c = (unsigned char) *++cptr;
960
	if (c == EOF)
961
		unexpected_EOF();
962
963
	for (;;) {
964
		if (isdigit(c)) {
965
			SRexpect = get_number();
966
			break;
967
		}
968
		/*
969
	         * Looking for number before EOL.
970
	         * Spaces, tabs, and numbers are ok.
971
	         * Words, punc., etc. are syntax errors.
972
	         */
973
		else if (c == '\n' || isalpha(c) || !isspace(c)) {
974
			syntax_error(lineno, line, cptr);
975
		} else {
976
			c = (unsigned char) *++cptr;
977
			if (c == EOF)
978
				unexpected_EOF();
979
		}
980
	}
981
}
982
983
984
void
985
declare_types(void)
986
{
987
	int c;
988
	bucket *bp;
989
	char *tag;
990
991
114
	c = nextc();
992
57
	if (c == EOF)
993
		unexpected_EOF();
994
57
	if (c != '<')
995
		syntax_error(lineno, line, cptr);
996
57
	tag = get_tag();
997
998
253
	for (;;) {
999
253
		c = nextc();
1000
253
		if (isalpha(c) || c == '_' || c == '.' || c == '$')
1001
196
			bp = get_name();
1002
57
		else if (c == '\'' || c == '"')
1003
			bp = get_literal();
1004
		else
1005
			return;
1006
1007

196
		if (bp->tag && tag != bp->tag)
1008
			retyped_warning(bp->name);
1009
196
		bp->tag = tag;
1010
	}
1011
57
}
1012
1013
1014
void
1015
declare_start(void)
1016
{
1017
	int c;
1018
	bucket *bp;
1019
1020
14
	c = nextc();
1021
7
	if (c == EOF)
1022
		unexpected_EOF();
1023
7
	if (!isalpha(c) && c != '_' && c != '.' && c != '$')
1024
		syntax_error(lineno, line, cptr);
1025
7
	bp = get_name();
1026
7
	if (bp->class == TERM)
1027
		terminal_start(bp->name);
1028

7
	if (goal && goal != bp)
1029
		restarted_warning();
1030
7
	goal = bp;
1031
7
}
1032
1033
1034
void
1035
read_declarations(void)
1036
{
1037
	int c, k;
1038
1039
18
	cache_size = 256;
1040
9
	cache = malloc(cache_size);
1041
9
	if (cache == NULL)
1042
		no_space();
1043
1044
181
	for (;;) {
1045
181
		c = nextc();
1046
181
		if (c == EOF)
1047
			unexpected_EOF();
1048
181
		if (c != '%')
1049
			syntax_error(lineno, line, cptr);
1050



353
		switch (k = keyword()) {
1051
		case MARK:
1052
			return;
1053
1054
		case IDENT:
1055
			copy_ident();
1056
			break;
1057
1058
		case TEXT:
1059
9
			copy_text();
1060
9
			break;
1061
1062
		case UNION:
1063
9
			copy_union();
1064
9
			break;
1065
1066
		case TOKEN:
1067
		case LEFT:
1068
		case RIGHT:
1069
		case NONASSOC:
1070
90
			declare_tokens(k);
1071
90
			break;
1072
1073
		case EXPECT:
1074
			declare_expect(k);
1075
			break;
1076
1077
		case TYPE:
1078
57
			declare_types();
1079
57
			break;
1080
1081
		case START:
1082
7
			declare_start();
1083
7
			break;
1084
		}
1085
	}
1086
9
}
1087
1088
1089
void
1090
initialize_grammar(void)
1091
{
1092
18
	nitems = 4;
1093
9
	maxitems = 300;
1094
9
	pitem = calloc(maxitems, sizeof(bucket *));
1095
9
	if (pitem == NULL)
1096
		no_space();
1097
1098
9
	nrules = 3;
1099
9
	maxrules = 100;
1100
9
	plhs = reallocarray(NULL, maxrules, sizeof(bucket *));
1101
9
	if (plhs == NULL)
1102
		no_space();
1103
9
	plhs[0] = 0;
1104
9
	plhs[1] = 0;
1105
9
	plhs[2] = 0;
1106
9
	rprec = reallocarray(NULL, maxrules, sizeof(short));
1107
9
	if (rprec == NULL)
1108
		no_space();
1109
9
	rprec[0] = 0;
1110
9
	rprec[1] = 0;
1111
9
	rprec[2] = 0;
1112
9
	rassoc = reallocarray(NULL, maxrules, sizeof(char));
1113
9
	if (rassoc == NULL)
1114
		no_space();
1115
9
	rassoc[0] = TOKEN;
1116
9
	rassoc[1] = TOKEN;
1117
9
	rassoc[2] = TOKEN;
1118
9
}
1119
1120
1121
void
1122
expand_items(void)
1123
{
1124
14
	int olditems = maxitems;
1125
1126
7
	maxitems += 300;
1127
7
	pitem = reallocarray(pitem, maxitems, sizeof(bucket *));
1128
7
	if (pitem == NULL)
1129
		no_space();
1130
7
	memset(pitem + olditems, 0, (maxitems - olditems) * sizeof(bucket *));
1131
7
}
1132
1133
1134
void
1135
expand_rules(void)
1136
{
1137
4
	maxrules += 100;
1138
2
	plhs = reallocarray(plhs, maxrules, sizeof(bucket *));
1139
2
	if (plhs == NULL)
1140
		no_space();
1141
2
	rprec = reallocarray(rprec, maxrules, sizeof(short));
1142
2
	if (rprec == NULL)
1143
		no_space();
1144
2
	rassoc = reallocarray(rassoc, maxrules, sizeof(char));
1145
2
	if (rassoc == NULL)
1146
		no_space();
1147
2
}
1148
1149
1150
void
1151
advance_to_start(void)
1152
{
1153
	int c;
1154
	bucket *bp;
1155
	char *s_cptr;
1156
	int s_lineno;
1157
1158
18
	for (;;) {
1159
9
		c = nextc();
1160
9
		if (c != '%')
1161
			break;
1162
		s_cptr = cptr;
1163
		switch (keyword()) {
1164
		case MARK:
1165
			no_grammar();
1166
1167
		case TEXT:
1168
			copy_text();
1169
			break;
1170
1171
		case START:
1172
			declare_start();
1173
			break;
1174
1175
		default:
1176
			syntax_error(lineno, line, s_cptr);
1177
		}
1178
	}
1179
1180
9
	c = nextc();
1181
9
	if (!isalpha(c) && c != '_' && c != '.' && c != '_')
1182
		syntax_error(lineno, line, cptr);
1183
9
	bp = get_name();
1184
9
	if (goal == NULL) {
1185
2
		if (bp->class == TERM)
1186
			terminal_start(bp->name);
1187
2
		goal = bp;
1188
2
	}
1189
9
	s_lineno = lineno;
1190
9
	c = nextc();
1191
9
	if (c == EOF)
1192
		unexpected_EOF();
1193
9
	if (c != ':')
1194
		syntax_error(lineno, line, cptr);
1195
9
	start_rule(bp, s_lineno);
1196
9
	++cptr;
1197
9
}
1198
1199
1200
void
1201
start_rule(bucket * bp, int s_lineno)
1202
{
1203
1728
	if (bp->class == TERM)
1204
		terminal_lhs(s_lineno);
1205
864
	bp->class = NONTERM;
1206
864
	if (nrules >= maxrules)
1207
2
		expand_rules();
1208
864
	plhs[nrules] = bp;
1209
864
	rprec[nrules] = UNDEFINED;
1210
864
	rassoc[nrules] = TOKEN;
1211
864
}
1212
1213
1214
void
1215
end_rule(void)
1216
{
1217
	int i;
1218
1219

1798
	if (!last_was_action && plhs[nrules]->tag) {
1220
176
		for (i = nitems - 1; pitem[i]; --i)
1221
			continue;
1222

132
		if (i == maxitems - 1 || pitem[i + 1] == 0 ||
1223
44
		    pitem[i + 1]->tag != plhs[nrules]->tag)
1224
			default_action_warning();
1225
	}
1226
864
	last_was_action = 0;
1227
864
	if (nitems >= maxitems)
1228
		expand_items();
1229
864
	pitem[nitems] = 0;
1230
864
	++nitems;
1231
864
	++nrules;
1232
864
}
1233
1234
1235
void
1236
insert_empty_rule(void)
1237
{
1238
	bucket *bp, **bpp;
1239
1240
60
	assert(cache);
1241
30
	snprintf(cache, cache_size, "$$%d", ++gensym);
1242
30
	bp = make_bucket(cache);
1243
30
	last_symbol->next = bp;
1244
30
	last_symbol = bp;
1245
30
	bp->tag = plhs[nrules]->tag;
1246
30
	bp->class = NONTERM;
1247
1248
30
	if ((nitems += 2) > maxitems)
1249
		expand_items();
1250
30
	bpp = pitem + nitems - 1;
1251
30
	*bpp-- = bp;
1252
152
	while ((bpp[0] = bpp[-1]))
1253
46
		--bpp;
1254
1255
30
	if (++nrules >= maxrules)
1256
		expand_rules();
1257
30
	plhs[nrules] = plhs[nrules - 1];
1258
30
	plhs[nrules - 1] = bp;
1259
30
	rprec[nrules] = rprec[nrules - 1];
1260
30
	rprec[nrules - 1] = 0;
1261
30
	rassoc[nrules] = rassoc[nrules - 1];
1262
30
	rassoc[nrules - 1] = TOKEN;
1263
30
}
1264
1265
1266
void
1267
add_symbol(void)
1268
{
1269
	int c;
1270
	bucket *bp;
1271
5422
	int s_lineno = lineno;
1272
1273
2711
	c = (unsigned char) *cptr;
1274
2711
	if (c == '\'' || c == '"')
1275
56
		bp = get_literal();
1276
	else
1277
2655
		bp = get_name();
1278
1279
2711
	c = nextc();
1280
2711
	if (c == ':') {
1281
192
		end_rule();
1282
192
		start_rule(bp, s_lineno);
1283
192
		++cptr;
1284
192
		return;
1285
	}
1286
2519
	if (last_was_action)
1287
30
		insert_empty_rule();
1288
2519
	last_was_action = 0;
1289
1290
2519
	if (++nitems > maxitems)
1291
7
		expand_items();
1292
2519
	pitem[nitems - 1] = bp;
1293
5230
}
1294
1295
1296
void
1297
copy_action(void)
1298
{
1299
	int c, i, n, depth, quote;
1300
	char *tag;
1301
1648
	FILE *f = action_file;
1302
824
	int a_lineno = lineno;
1303
824
	char *a_line = dup_line();
1304
824
	char *a_cptr = a_line + (cptr - line);
1305
1306
824
	if (last_was_action)
1307
		insert_empty_rule();
1308
824
	last_was_action = 1;
1309
1310
824
	fprintf(f, "case %d:\n", nrules - 2);
1311
824
	if (!lflag)
1312
824
		fprintf(f, line_format, lineno, input_file_name);
1313
824
	if (*cptr == '=')
1314
		++cptr;
1315
1316
	n = 0;
1317
6646
	for (i = nitems - 1; pitem[i]; --i)
1318
2499
		++n;
1319
1320
824
	depth = 0;
1321
loop:
1322
56252
	c = (unsigned char) *cptr;
1323
56252
	if (c == '$') {
1324
2645
		if (cptr[1] == '<') {
1325
26
			int d_lineno = lineno;
1326
26
			char *d_line = dup_line();
1327
26
			char *d_cptr = d_line + (cptr - line);
1328
1329
26
			++cptr;
1330
26
			tag = get_tag();
1331
26
			c = (unsigned char) *cptr;
1332
26
			if (c == '$') {
1333
				fprintf(f, "yyval.%s", tag);
1334
				++cptr;
1335
				free(d_line);
1336
				goto loop;
1337
26
			} else if (isdigit(c)) {
1338
26
				i = get_number();
1339
26
				if (i > n)
1340
					dollar_warning(d_lineno, i);
1341
26
				fprintf(f, "yyvsp[%d].%s", i - n, tag);
1342
26
				free(d_line);
1343
26
				goto loop;
1344
			} else if (c == '-' && isdigit((unsigned char) cptr[1])) {
1345
				++cptr;
1346
				i = -get_number() - n;
1347
				fprintf(f, "yyvsp[%d].%s", i, tag);
1348
				free(d_line);
1349
				goto loop;
1350
			} else
1351
				dollar_error(d_lineno, d_line, d_cptr);
1352
2619
		} else if (cptr[1] == '$') {
1353
673
			if (ntags) {
1354
673
				tag = plhs[nrules]->tag;
1355
673
				if (tag == NULL)
1356
					untyped_lhs();
1357
673
				fprintf(f, "yyval.%s", tag);
1358
673
			} else
1359
				fprintf(f, "yyval");
1360
673
			cptr += 2;
1361
673
			goto loop;
1362
1946
		} else if (isdigit((unsigned char) cptr[1])) {
1363
1946
			++cptr;
1364
1946
			i = get_number();
1365
1946
			if (ntags) {
1366

3892
				if (i <= 0 || i > n)
1367
					unknown_rhs(i);
1368
1946
				tag = pitem[nitems + i - n - 1]->tag;
1369
1946
				if (tag == NULL)
1370
					untyped_rhs(i, pitem[nitems + i - n - 1]->name);
1371
1946
				fprintf(f, "yyvsp[%d].%s", i - n, tag);
1372
1946
			} else {
1373
				if (i > n)
1374
					dollar_warning(lineno, i);
1375
				fprintf(f, "yyvsp[%d]", i - n);
1376
			}
1377
1946
			goto loop;
1378
		} else if (cptr[1] == '-') {
1379
			cptr += 2;
1380
			i = get_number();
1381
			if (ntags)
1382
				unknown_rhs(-i);
1383
			fprintf(f, "yyvsp[%d]", -i - n);
1384
			goto loop;
1385
		}
1386
	}
1387
53607
	if (isalpha(c) || c == '_' || c == '$') {
1388
4914
		do {
1389
59120
			putc(c, f);
1390
29560
			c = (unsigned char) *++cptr;
1391

34474
		} while (isalnum(c) || c == '_' || c == '$');
1392
4914
		goto loop;
1393
	}
1394
97386
	putc(c, f);
1395
48693
	++cptr;
1396


48693
	switch (c) {
1397
	case '\n':
1398
next_line:
1399
4026
		get_line();
1400
4026
		if (line)
1401
4026
			goto loop;
1402
		unterminated_action(a_lineno, a_line, a_cptr);
1403
1404
	case ';':
1405
2183
		if (depth > 0)
1406
2183
			goto loop;
1407
		fprintf(f, "\nbreak;\n");
1408
		free(a_line);
1409
		return;
1410
1411
	case '{':
1412
1209
		++depth;
1413
1209
		goto loop;
1414
1415
	case '}':
1416
1209
		if (--depth > 0)
1417
385
			goto loop;
1418
824
		fprintf(f, "\nbreak;\n");
1419
824
		free(a_line);
1420
824
		return;
1421
1422
	case '\'':
1423
	case '"': {
1424
437
		int s_lineno = lineno;
1425
437
		char *s_line = dup_line();
1426
437
		char *s_cptr = s_line + (cptr - line - 1);
1427
1428
		quote = c;
1429
7316
		for (;;) {
1430
7316
			c = (unsigned char) *cptr++;
1431
14632
			putc(c, f);
1432
7316
			if (c == quote) {
1433
437
				free(s_line);
1434
				goto loop;
1435
			}
1436
6879
			if (c == '\n')
1437
				unterminated_string(s_lineno, s_line, s_cptr);
1438
6879
			if (c == '\\') {
1439
2
				c = (unsigned char) *cptr++;
1440
4
				putc(c, f);
1441
2
				if (c == '\n') {
1442
					get_line();
1443
					if (line == NULL)
1444
						unterminated_string(s_lineno, s_line, s_cptr);
1445
				}
1446
			}
1447
		}
1448
	}
1449
1450
	case '/':
1451
93
		c = (unsigned char) *cptr;
1452
93
		if (c == '/') {
1453
			putc('*', f);
1454
			while ((c = (unsigned char) *++cptr) != '\n') {
1455
				if (c == '*' && cptr[1] == '/')
1456
					fprintf(f, "* ");
1457
				else
1458
					putc(c, f);
1459
			}
1460
			fprintf(f, "*/\n");
1461
			goto next_line;
1462
		}
1463
93
		if (c == '*') {
1464
84
			int c_lineno = lineno;
1465
84
			char *c_line = dup_line();
1466
84
			char *c_cptr = c_line + (cptr - line - 1);
1467
1468
168
			putc('*', f);
1469
84
			++cptr;
1470
4951
			for (;;) {
1471
4951
				c = (unsigned char) *cptr++;
1472
9902
				putc(c, f);
1473

5093
				if (c == '*' && *cptr == '/') {
1474
168
					putc('/', f);
1475
84
					++cptr;
1476
84
					free(c_line);
1477
					goto loop;
1478
				}
1479
4867
				if (c == '\n') {
1480
79
					get_line();
1481
79
					if (line == NULL)
1482
						unterminated_comment(c_lineno, c_line, c_cptr);
1483
				}
1484
			}
1485
		}
1486
9
		goto loop;
1487
1488
	default:
1489
39536
		goto loop;
1490
	}
1491
824
}
1492
1493
1494
int
1495
mark_symbol(void)
1496
{
1497
	int c;
1498
	bucket *bp = NULL;
1499
1500
30
	c = (unsigned char) cptr[1];
1501
15
	if (c == '%' || c == '\\') {
1502
9
		cptr += 2;
1503
9
		return (1);
1504
	}
1505
6
	if (c == '=')
1506
		cptr += 2;
1507

12
	else if ((c == 'p' || c == 'P') &&
1508
6
	    ((c = cptr[2]) == 'r' || c == 'R') &&
1509
6
	    ((c = cptr[3]) == 'e' || c == 'E') &&
1510
6
	    ((c = cptr[4]) == 'c' || c == 'C') &&
1511
18
	    ((c = (unsigned char) cptr[5], !IS_IDENT(c))))
1512
		cptr += 5;
1513
	else
1514
		syntax_error(lineno, line, cptr);
1515
1516
6
	c = nextc();
1517
6
	if (isalpha(c) || c == '_' || c == '.' || c == '$')
1518
6
		bp = get_name();
1519
	else if (c == '\'' || c == '"')
1520
		bp = get_literal();
1521
	else {
1522
		syntax_error(lineno, line, cptr);
1523
		/* NOTREACHED */
1524
	}
1525
1526

6
	if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
1527
		prec_redeclared();
1528
1529
6
	rprec[nrules] = bp->prec;
1530
6
	rassoc[nrules] = bp->assoc;
1531
6
	return (0);
1532
15
}
1533
1534
1535
void
1536
read_grammar(void)
1537
{
1538
	int c;
1539
1540
18
	initialize_grammar();
1541
9
	advance_to_start();
1542
1543
4213
	for (;;) {
1544
4213
		c = nextc();
1545
4213
		if (c == EOF)
1546
			break;
1547
8426
		if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' ||
1548
4213
		    c == '"')
1549
2711
			add_symbol();
1550
1502
		else if (c == '{' || c == '=')
1551
824
			copy_action();
1552
678
		else if (c == '|') {
1553
663
			end_rule();
1554
663
			start_rule(plhs[nrules - 1], 0);
1555
663
			++cptr;
1556
678
		} else if (c == '%') {
1557
15
			if (mark_symbol())
1558
				break;
1559
		} else
1560
			syntax_error(lineno, line, cptr);
1561
	}
1562
9
	end_rule();
1563
9
}
1564
1565
1566
void
1567
free_tags(void)
1568
{
1569
	int i;
1570
1571
18
	if (tag_table == NULL)
1572
		return;
1573
1574
88
	for (i = 0; i < ntags; ++i) {
1575
35
		assert(tag_table[i]);
1576
35
		free(tag_table[i]);
1577
	}
1578
9
	free(tag_table);
1579
18
}
1580
1581
1582
void
1583
pack_names(void)
1584
{
1585
	bucket *bp;
1586
	char *p, *s, *t;
1587
1588
18
	name_pool_size = 13;	/* 13 == sizeof("$end") + sizeof("$accept") */
1589
1680
	for (bp = first_symbol; bp; bp = bp->next)
1590
831
		name_pool_size += strlen(bp->name) + 1;
1591
9
	name_pool = malloc(name_pool_size);
1592
9
	if (name_pool == NULL)
1593
		no_space();
1594
1595
9
	strlcpy(name_pool, "$accept", name_pool_size);
1596
9
	strlcpy(name_pool + 8, "$end", name_pool_size - 8);
1597
9
	t = name_pool + 13;
1598
1680
	for (bp = first_symbol; bp; bp = bp->next) {
1599
		p = t;
1600
831
		s = bp->name;
1601
5763
		while ((*t++ = *s++))
1602
4101
			continue;
1603
831
		free(bp->name);
1604
831
		bp->name = p;
1605
	}
1606
9
}
1607
1608
1609
void
1610
check_symbols(void)
1611
{
1612
	bucket *bp;
1613
1614
18
	if (goal->class == UNKNOWN)
1615
		undefined_goal(goal->name);
1616
1617
1680
	for (bp = first_symbol; bp; bp = bp->next) {
1618
831
		if (bp->class == UNKNOWN) {
1619
			undefined_symbol_warning(bp->name);
1620
			bp->class = TERM;
1621
		}
1622
	}
1623
9
}
1624
1625
1626
void
1627
pack_symbols(void)
1628
{
1629
	bucket *bp;
1630
	bucket **v;
1631
	int i, j, k, n;
1632
1633
18
	nsyms = 2;
1634
9
	ntokens = 1;
1635
1680
	for (bp = first_symbol; bp; bp = bp->next) {
1636
831
		++nsyms;
1637
831
		if (bp->class == TERM)
1638
600
			++ntokens;
1639
	}
1640
9
	start_symbol = ntokens;
1641
9
	nvars = nsyms - ntokens;
1642
1643
9
	symbol_name = reallocarray(NULL, nsyms, sizeof(char *));
1644
9
	if (symbol_name == NULL)
1645
		no_space();
1646
9
	symbol_value = reallocarray(NULL, nsyms, sizeof(short));
1647
9
	if (symbol_value == NULL)
1648
		no_space();
1649
9
	symbol_prec = reallocarray(NULL, nsyms, sizeof(short));
1650
9
	if (symbol_prec == NULL)
1651
		no_space();
1652
9
	symbol_assoc = malloc(nsyms);
1653
9
	if (symbol_assoc == NULL)
1654
		no_space();
1655
1656
9
	v = reallocarray(NULL, nsyms, sizeof(bucket *));
1657
9
	if (v == NULL)
1658
		no_space();
1659
1660
9
	v[0] = 0;
1661
9
	v[start_symbol] = 0;
1662
1663
	i = 1;
1664
9
	j = start_symbol + 1;
1665
1680
	for (bp = first_symbol; bp; bp = bp->next) {
1666
831
		if (bp->class == TERM)
1667
600
			v[i++] = bp;
1668
		else
1669
231
			v[j++] = bp;
1670
	}
1671

18
	assert(i == ntokens && j == nsyms);
1672
1673
1218
	for (i = 1; i < ntokens; ++i)
1674
600
		v[i]->index = i;
1675
1676
9
	goal->index = start_symbol + 1;
1677
9
	k = start_symbol + 2;
1678
480
	while (++i < nsyms)
1679
231
		if (v[i] != goal) {
1680
222
			v[i]->index = k;
1681
222
			++k;
1682
222
		}
1683
9
	goal->value = 0;
1684
	k = 1;
1685
480
	for (i = start_symbol + 1; i < nsyms; ++i) {
1686
231
		if (v[i] != goal) {
1687
222
			v[i]->value = k;
1688
222
			++k;
1689
222
		}
1690
	}
1691
1692
	k = 0;
1693
1218
	for (i = 1; i < ntokens; ++i) {
1694
600
		n = v[i]->value;
1695
600
		if (n > 256) {
1696
			for (j = k++; j > 0 && symbol_value[j - 1] > n; --j)
1697
				symbol_value[j] = symbol_value[j - 1];
1698
			symbol_value[j] = n;
1699
		}
1700
	}
1701
1702
9
	if (v[1]->value == UNDEFINED)
1703
9
		v[1]->value = 256;
1704
1705
	j = 0;
1706
	n = 257;
1707
1200
	for (i = 2; i < ntokens; ++i) {
1708
591
		if (v[i]->value == UNDEFINED) {
1709

1122
			while (j < k && n == symbol_value[j]) {
1710
				while (++j < k && n == symbol_value[j])
1711
					continue;
1712
				++n;
1713
			}
1714
561
			v[i]->value = n;
1715
561
			++n;
1716
561
		}
1717
	}
1718
1719
9
	symbol_name[0] = name_pool + 8;
1720
9
	symbol_value[0] = 0;
1721
9
	symbol_prec[0] = 0;
1722
9
	symbol_assoc[0] = TOKEN;
1723
1218
	for (i = 1; i < ntokens; ++i) {
1724
600
		symbol_name[i] = v[i]->name;
1725
600
		symbol_value[i] = v[i]->value;
1726
600
		symbol_prec[i] = v[i]->prec;
1727
600
		symbol_assoc[i] = v[i]->assoc;
1728
	}
1729
9
	symbol_name[start_symbol] = name_pool;
1730
9
	symbol_value[start_symbol] = -1;
1731
9
	symbol_prec[start_symbol] = 0;
1732
9
	symbol_assoc[start_symbol] = TOKEN;
1733
480
	for (++i; i < nsyms; ++i) {
1734
231
		k = v[i]->index;
1735
231
		symbol_name[k] = v[i]->name;
1736
231
		symbol_value[k] = v[i]->value;
1737
231
		symbol_prec[k] = v[i]->prec;
1738
231
		symbol_assoc[k] = v[i]->assoc;
1739
	}
1740
1741
9
	free(v);
1742
9
}
1743
1744
1745
void
1746
pack_grammar(void)
1747
{
1748
	int i, j;
1749
	int assoc, pprec;
1750
1751
18
	ritem = reallocarray(NULL, nitems, sizeof(short));
1752
9
	if (ritem == NULL)
1753
		no_space();
1754
9
	rlhs = reallocarray(NULL, nrules, sizeof(short));
1755
9
	if (rlhs == NULL)
1756
		no_space();
1757
9
	rrhs = reallocarray(NULL, nrules + 1, sizeof(short));
1758
9
	if (rrhs == NULL)
1759
		no_space();
1760
9
	rprec = reallocarray(rprec, nrules, sizeof(short));
1761
9
	if (rprec == NULL)
1762
		no_space();
1763
9
	rassoc = realloc(rassoc, nrules);
1764
9
	if (rassoc == NULL)
1765
		no_space();
1766
1767
9
	ritem[0] = -1;
1768
9
	ritem[1] = goal->index;
1769
9
	ritem[2] = 0;
1770
9
	ritem[3] = -2;
1771
9
	rlhs[0] = 0;
1772
9
	rlhs[1] = 0;
1773
9
	rlhs[2] = start_symbol;
1774
9
	rrhs[0] = 0;
1775
9
	rrhs[1] = 0;
1776
9
	rrhs[2] = 1;
1777
1778
	j = 4;
1779
1806
	for (i = 3; i < nrules; ++i) {
1780
894
		rlhs[i] = plhs[i]->index;
1781
894
		rrhs[i] = j;
1782
		assoc = TOKEN;
1783
		pprec = 0;
1784
6886
		while (pitem[j]) {
1785
2549
			ritem[j] = pitem[j]->index;
1786
2549
			if (pitem[j]->class == TERM) {
1787
1723
				pprec = pitem[j]->prec;
1788
1723
				assoc = pitem[j]->assoc;
1789
1723
			}
1790
2549
			++j;
1791
		}
1792
894
		ritem[j] = -i;
1793
894
		++j;
1794
894
		if (rprec[i] == UNDEFINED) {
1795
858
			rprec[i] = pprec;
1796
858
			rassoc[i] = assoc;
1797
858
		}
1798
	}
1799
9
	rrhs[i] = j;
1800
1801
9
	free(plhs);
1802
9
	free(pitem);
1803
9
}
1804
1805
1806
void
1807
print_grammar(void)
1808
{
1809
	int i, j, k;
1810
	int spacing = 0;
1811
18
	FILE *f = verbose_file;
1812
1813
9
	if (!vflag)
1814
9
		return;
1815
1816
	k = 1;
1817
	for (i = 2; i < nrules; ++i) {
1818
		if (rlhs[i] != rlhs[i - 1]) {
1819
			if (i != 2)
1820
				fprintf(f, "\n");
1821
			fprintf(f, "%4d  %s :", i - 2, symbol_name[rlhs[i]]);
1822
			spacing = strlen(symbol_name[rlhs[i]]) + 1;
1823
		} else {
1824
			fprintf(f, "%4d  ", i - 2);
1825
			j = spacing;
1826
			while (--j >= 0)
1827
				putc(' ', f);
1828
			putc('|', f);
1829
		}
1830
1831
		while (ritem[k] >= 0) {
1832
			fprintf(f, " %s", symbol_name[ritem[k]]);
1833
			++k;
1834
		}
1835
		++k;
1836
		putc('\n', f);
1837
	}
1838
9
}
1839
1840
1841
void
1842
reader(void)
1843
{
1844
18
	write_section(banner);
1845
9
	create_symbol_table();
1846
9
	read_declarations();
1847
9
	read_grammar();
1848
9
	free_symbol_table();
1849
9
	free_tags();
1850
9
	pack_names();
1851
9
	check_symbols();
1852
9
	pack_symbols();
1853
9
	pack_grammar();
1854
9
	free_symbols();
1855
9
	print_grammar();
1856
9
}