GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/yacc/reader.c Lines: 734 1084 67.7 %
Date: 2017-11-07 Branches: 385 807 47.7 %

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
101974
	assert(cinc >= 0);
113
50987
	if (cinc >= cache_size) {
114
		cache_size += 256;
115
		cache = realloc(cache, cache_size);
116
		if (cache == NULL)
117
			no_space();
118
	}
119
50987
	cache[cinc] = c;
120
50987
	++cinc;
121
50987
}
122
123
124
void
125
get_line(void)
126
{
127
25260
	FILE *f = input_file;
128
	int c, i;
129
130


63150
	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
12630
	if (line == NULL || linesize != (LINESIZE + 1)) {
140
22
		free(line);
141
22
		linesize = LINESIZE + 1;
142
22
		line = malloc(linesize);
143
22
		if (line == NULL)
144
			no_space();
145
	}
146
	i = 0;
147
12630
	++lineno;
148
12630
	for (;;) {
149
302413
		line[i] = c;
150
302413
		if (c == '\n') {
151
12630
			cptr = line;
152
12630
			return;
153
		}
154
289783
		if (++i >= linesize) {
155
7
			linesize += LINESIZE;
156
7
			line = realloc(line, linesize);
157
7
			if (line == NULL)
158
				no_space();
159
		}
160

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

10074
		if (*s == '*' && s[1] == '/') {
204
179
			cptr = s + 2;
205
179
			free(st_line);
206
			return;
207
		}
208
9561
		if (*s == '\n') {
209
174
			get_line();
210
174
			if (line == NULL)
211
				unterminated_comment(st_lineno, st_line, st_cptr);
212
174
			s = cptr;
213
174
		} else
214
9387
			++s;
215
	}
216
179
}
217
218
219
int
220
nextc(void)
221
{
222
	char *s;
223
224
29262
	if (line == NULL) {
225
15
		get_line();
226
15
		if (line == NULL)
227
			return (EOF);
228
	}
229
14631
	s = cptr;
230
14631
	for (;;) {
231


33638
		switch (*s) {
232
		case '\n':
233
3861
			get_line();
234
3861
			if (line == NULL)
235
				return (EOF);
236
3861
			s = cptr;
237
3861
			break;
238
239
		case ' ':
240
		case '\t':
241
		case '\f':
242
		case '\r':
243
		case '\v':
244
		case ',':
245
		case ';':
246
14967
			++s;
247
14967
			break;
248
249
		case '\\':
250
			cptr = s;
251
			return ('%');
252
253
		case '/':
254
179
			if (s[1] == '*') {
255
179
				cptr = s;
256
179
				skip_comment();
257
179
				s = cptr;
258
179
				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
14631
			cptr = s;
270
14631
			return ((unsigned char) *s);
271
		}
272
	}
273
14631
}
274
275
276
int
277
keyword(void)
278
{
279
	int c;
280
832
	char *t_cptr = cptr;
281
282
416
	c = (unsigned char) *++cptr;
283
416
	if (isalpha(c)) {
284
386
		cinc = 0;
285
2192
		for (;;) {
286
2192
			if (isalpha(c)) {
287
1806
				if (isupper(c))
288
					c = tolower(c);
289
1806
				cachec(c);
290
2192
			} else if (isdigit(c) || c == '_' || c == '.' || c == '$')
291
				cachec(c);
292
			else
293
				break;
294
1806
			c = (unsigned char) *++cptr;
295
		}
296
386
		cachec(NUL);
297
298

633
		if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0)
299
139
			return (TOKEN);
300
247
		if (strcmp(cache, "type") == 0)
301
154
			return (TYPE);
302
93
		if (strcmp(cache, "left") == 0)
303
39
			return (LEFT);
304
54
		if (strcmp(cache, "right") == 0)
305
9
			return (RIGHT);
306

67
		if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0)
307
23
			return (NONASSOC);
308
22
		if (strcmp(cache, "start") == 0)
309
8
			return (START);
310
14
		if (strcmp(cache, "union") == 0)
311
14
			return (UNION);
312
		if (strcmp(cache, "ident") == 0)
313
			return (IDENT);
314
		if (strcmp(cache, "expect") == 0)
315
			return (EXPECT);
316
	} else {
317
30
		++cptr;
318
30
		if (c == '{')
319
15
			return (TEXT);
320
15
		if (c == '%' || c == '\\')
321
15
			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
416
}
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
30
	FILE *f = text_file;
372
	int need_newline = 0;
373
15
	int t_lineno = lineno;
374
15
	char *t_line = dup_line();
375
15
	char *t_cptr = t_line + (cptr - line - 2);
376
377
15
	if (*cptr == '\n') {
378
15
		get_line();
379
15
		if (line == NULL)
380
			unterminated_text(t_lineno, t_line, t_cptr);
381
	}
382
15
	if (!lflag)
383
15
		fprintf(f, line_format, lineno, input_file_name);
384
385
loop:
386
22430
	c = (unsigned char) *cptr++;
387

22430
	switch (c) {
388
	case '\n':
389
next_line:
390
2306
		putc('\n', f);
391
		need_newline = 0;
392
1153
		get_line();
393
1153
		if (line)
394
			goto loop;
395
		unterminated_text(t_lineno, t_line, t_cptr);
396
397
	case '\'':
398
	case '"': {
399
50
		int s_lineno = lineno;
400
50
		char *s_line = dup_line();
401
50
		char *s_cptr = s_line + (cptr - line - 1);
402
403
		quote = c;
404
100
		putc(c, f);
405
		for (;;) {
406
392
			c = (unsigned char) *cptr++;
407
784
			putc(c, f);
408
392
			if (c == quote) {
409
				need_newline = 1;
410
50
				free(s_line);
411
				goto loop;
412
			}
413
342
			if (c == '\n')
414
				unterminated_string(s_lineno, s_line, s_cptr);
415
342
			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
198
		putc(c, f);
429
		need_newline = 1;
430
99
		c = (unsigned char) *cptr;
431
99
		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
99
		if (c == '*') {
443
55
			int c_lineno = lineno;
444
55
			char *c_line = dup_line();
445
55
			char *c_cptr = c_line + (cptr - line - 1);
446
447
110
			putc('*', f);
448
55
			++cptr;
449
55
			for (;;) {
450
9464
				c = (unsigned char) *cptr++;
451
18928
				putc(c, f);
452

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

1233
	switch (c) {
518
	case '\n':
519
next_line:
520
78
		get_line();
521
78
		if (line == NULL)
522
			unterminated_union(u_lineno, u_line, u_cptr);
523
		goto loop;
524
525
	case '{':
526
17
		++depth;
527
17
		goto loop;
528
529
	case '}':
530
17
		if (--depth == 0) {
531
14
			fprintf(text_file, " YYSTYPE;\n");
532
14
			fprintf(text_file, "#endif /* YYSTYPE_DEFINED */\n");
533
14
			free(u_line);
534
			return;
535
		}
536
		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
		goto loop;
627
	}
628
14
}
629
630
631
bucket *
632
get_literal(void)
633
{
634
	int c, quote, i, n;
635
432
	char *s;
636
	bucket *bp;
637
216
	int s_lineno = lineno;
638
216
	char *s_line = dup_line();
639
216
	char *s_cptr = s_line + (cptr - line);
640
641
216
	quote = (unsigned char) *cptr++;
642
216
	cinc = 0;
643
432
	for (;;) {
644
432
		c = (unsigned char) *cptr++;
645
432
		if (c == quote)
646
			break;
647
216
		if (c == '\n')
648
			unterminated_string(s_lineno, s_line, s_cptr);
649
216
		if (c == '\\') {
650
44
			char *c_cptr = cptr - 1;
651
			unsigned long ulval;
652
653
44
			c = (unsigned char) *cptr++;
654




44
			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
22
				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
22
		}
708
216
		cachec(c);
709
	}
710
216
	free(s_line);
711
712
216
	n = cinc;
713
216
	s = malloc(n);
714
216
	if (s == NULL)
715
		no_space();
716
717
216
	memcpy(s, cache, n);
718
719
216
	cinc = 0;
720
216
	if (n == 1)
721
216
		cachec('\'');
722
	else
723
		cachec('"');
724
725
864
	for (i = 0; i < n; ++i) {
726
216
		c = ((unsigned char *) s)[i];
727

432
		if (c == '\\' || c == cache[0]) {
728
			cachec('\\');
729
			cachec(c);
730
216
		} else if (isprint(c))
731
194
			cachec(c);
732
		else {
733
22
			cachec('\\');
734


22
			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
22
				cachec('n');
746
22
				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
216
	if (n == 1)
766
216
		cachec('\'');
767
	else
768
		cachec('"');
769
770
216
	cachec(NUL);
771
216
	bp = lookup(cache);
772
216
	bp->class = TERM;
773

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

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

5617
	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
5617
	return (0);
799
5617
}
800
801
802
bucket *
803
get_name(void)
804
{
805
	int c;
806
807
11234
	cinc = 0;
808
92998
	for (c = (unsigned char) *cptr; IS_IDENT(c); c = (unsigned char) *++cptr)
809
40882
		cachec(c);
810
5617
	cachec(NUL);
811
812
5617
	if (is_reserved(cache))
813
		used_reserved(cache);
814
815
5617
	return (lookup(cache));
816
}
817
818
819
int
820
get_number(void)
821
{
822
	unsigned long ul;
823
6798
	char *p;
824
825
3399
	ul = strtoul(cptr, &p, 10);
826
3399
	if (ul > INT_MAX)
827
		syntax_error(lineno, line, cptr);
828
3399
	cptr = p;
829
6798
	return (ul);
830
3399
}
831
832
833
char *
834
get_tag(void)
835
{
836
	int c, i;
837
	char *s;
838
418
	int t_lineno = lineno;
839
209
	char *t_line = dup_line();
840
209
	char *t_cptr = t_line + (cptr - line);
841
842
209
	++cptr;
843
209
	c = nextc();
844
209
	if (c == EOF)
845
		unexpected_EOF();
846
209
	if (!isalpha(c) && c != '_' && c != '$')
847
		illegal_tag(t_lineno, t_line, t_cptr);
848
849
209
	cinc = 0;
850
209
	do {
851
985
		cachec(c);
852
985
		c = (unsigned char) *++cptr;
853
985
	} while (IS_IDENT(c));
854
209
	cachec(NUL);
855
856
209
	c = nextc();
857
209
	if (c == EOF)
858
		unexpected_EOF();
859
209
	if (c != '>')
860
		illegal_tag(t_lineno, t_line, t_cptr);
861
209
	free(t_line);
862
209
	++cptr;
863
864
2072
	for (i = 0; i < ntags; ++i) {
865
953
		if (strcmp(cache, tag_table[i]) == 0)
866
126
			return (tag_table[i]);
867
	}
868
869
83
	if (ntags >= tagmax) {
870
16
		tagmax += 16;
871
16
		tag_table = reallocarray(tag_table, tagmax, sizeof(char *));
872
16
		if (tag_table == NULL)
873
			no_space();
874
	}
875
83
	s = malloc(cinc);
876
83
	if (s == NULL)
877
		no_space();
878
83
	strlcpy(s, cache, cinc);
879
83
	tag_table[ntags] = s;
880
83
	++ntags;
881
83
	return (s);
882
209
}
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
420
	if (assoc != TOKEN)
894
71
		++prec;
895
896
210
	c = nextc();
897
210
	if (c == EOF)
898
		unexpected_EOF();
899
210
	if (c == '<') {
900
29
		tag = get_tag();
901
29
		c = nextc();
902
29
		if (c == EOF)
903
			unexpected_EOF();
904
	}
905
	for (;;) {
906
1043
		if (isalpha(c) || c == '_' || c == '.' || c == '$')
907
819
			bp = get_name();
908
224
		else if (c == '\'' || c == '"')
909
14
			bp = get_literal();
910
		else
911
			return;
912
913
833
		if (bp == goal)
914
			tokenized_start(bp->name);
915
833
		bp->class = TERM;
916
917
833
		if (tag) {
918

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

145
			if (bp->prec && prec != bp->prec)
924
				reprec_warning(bp->name);
925
145
			bp->assoc = assoc;
926
145
			bp->prec = prec;
927
145
		}
928
833
		c = nextc();
929
833
		if (c == EOF)
930
			unexpected_EOF();
931
833
		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
210
}
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
308
	c = nextc();
992
154
	if (c == EOF)
993
		unexpected_EOF();
994
154
	if (c != '<')
995
		syntax_error(lineno, line, cptr);
996
154
	tag = get_tag();
997
998
515
	for (;;) {
999
515
		c = nextc();
1000
515
		if (isalpha(c) || c == '_' || c == '.' || c == '$')
1001
361
			bp = get_name();
1002
154
		else if (c == '\'' || c == '"')
1003
			bp = get_literal();
1004
		else
1005
			return;
1006
1007

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

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



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

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

435
		if (i == maxitems - 1 || pitem[i + 1] == 0 ||
1223
145
		    pitem[i + 1]->tag != plhs[nrules]->tag)
1224
			default_action_warning();
1225
	}
1226
1797
	last_was_action = 0;
1227
1797
	if (nitems >= maxitems)
1228
5
		expand_items();
1229
1797
	pitem[nitems] = 0;
1230
1797
	++nitems;
1231
1797
	++nrules;
1232
1797
}
1233
1234
1235
void
1236
insert_empty_rule(void)
1237
{
1238
	bucket *bp, **bpp;
1239
1240
106
	assert(cache);
1241
53
	snprintf(cache, cache_size, "$$%d", ++gensym);
1242
53
	bp = make_bucket(cache);
1243
53
	last_symbol->next = bp;
1244
53
	last_symbol = bp;
1245
53
	bp->tag = plhs[nrules]->tag;
1246
53
	bp->class = NONTERM;
1247
1248
53
	if ((nitems += 2) > maxitems)
1249
		expand_items();
1250
53
	bpp = pitem + nitems - 1;
1251
53
	*bpp-- = bp;
1252
252
	while ((bpp[0] = bpp[-1]))
1253
73
		--bpp;
1254
1255
53
	if (++nrules >= maxrules)
1256
		expand_rules();
1257
53
	plhs[nrules] = plhs[nrules - 1];
1258
53
	plhs[nrules - 1] = bp;
1259
53
	rprec[nrules] = rprec[nrules - 1];
1260
53
	rprec[nrules - 1] = 0;
1261
53
	rassoc[nrules] = rassoc[nrules - 1];
1262
53
	rassoc[nrules - 1] = TOKEN;
1263
53
}
1264
1265
1266
void
1267
add_symbol(void)
1268
{
1269
	int c;
1270
	bucket *bp;
1271
9210
	int s_lineno = lineno;
1272
1273
4605
	c = (unsigned char) *cptr;
1274
4605
	if (c == '\'' || c == '"')
1275
202
		bp = get_literal();
1276
	else
1277
4403
		bp = get_name();
1278
1279
4605
	c = nextc();
1280
4605
	if (c == ':') {
1281
527
		end_rule();
1282
527
		start_rule(bp, s_lineno);
1283
527
		++cptr;
1284
527
		return;
1285
	}
1286
4078
	if (last_was_action)
1287
53
		insert_empty_rule();
1288
4078
	last_was_action = 0;
1289
1290
4078
	if (++nitems > maxitems)
1291
9
		expand_items();
1292
4078
	pitem[nitems - 1] = bp;
1293
8683
}
1294
1295
1296
void
1297
copy_action(void)
1298
{
1299
	int c, i, n, depth, quote;
1300
	char *tag;
1301
3002
	FILE *f = action_file;
1302
1501
	int a_lineno = lineno;
1303
1501
	char *a_line = dup_line();
1304
1501
	char *a_cptr = a_line + (cptr - line);
1305
1306
1501
	if (last_was_action)
1307
		insert_empty_rule();
1308
1501
	last_was_action = 1;
1309
1310
1501
	fprintf(f, "case %d:\n", nrules - 2);
1311
1501
	if (!lflag)
1312
1501
		fprintf(f, line_format, lineno, input_file_name);
1313
1501
	if (*cptr == '=')
1314
		++cptr;
1315
1316
	n = 0;
1317
10228
	for (i = nitems - 1; pitem[i]; --i)
1318
3613
		++n;
1319
1320
1501
	depth = 0;
1321
loop:
1322
100976
	c = (unsigned char) *cptr;
1323
100976
	if (c == '$') {
1324
5069
		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
5043
		} else if (cptr[1] == '$') {
1353
1670
			if (ntags) {
1354
1670
				tag = plhs[nrules]->tag;
1355
1670
				if (tag == NULL)
1356
					untyped_lhs();
1357
1670
				fprintf(f, "yyval.%s", tag);
1358
1670
			} else
1359
				fprintf(f, "yyval");
1360
1670
			cptr += 2;
1361
1670
			goto loop;
1362
3373
		} else if (isdigit((unsigned char) cptr[1])) {
1363
3373
			++cptr;
1364
3373
			i = get_number();
1365
3373
			if (ntags) {
1366

6746
				if (i <= 0 || i > n)
1367
					unknown_rhs(i);
1368
3373
				tag = pitem[nitems + i - n - 1]->tag;
1369
3373
				if (tag == NULL)
1370
					untyped_rhs(i, pitem[nitems + i - n - 1]->name);
1371
3373
				fprintf(f, "yyvsp[%d].%s", i - n, tag);
1372
3373
			} else {
1373
				if (i > n)
1374
					dollar_warning(lineno, i);
1375
				fprintf(f, "yyvsp[%d]", i - n);
1376
			}
1377
			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
95907
	if (isalpha(c) || c == '_' || c == '$') {
1388
		do {
1389
152218
			putc(c, f);
1390
76109
			c = (unsigned char) *++cptr;
1391
76109
		} while (isalnum(c) || c == '_' || c == '$');
1392
		goto loop;
1393
	}
1394
169074
	putc(c, f);
1395
117926
	++cptr;
1396


117926
	switch (c) {
1397
	case '\n':
1398
next_line:
1399
7142
		get_line();
1400
7142
		if (line)
1401
			goto loop;
1402
		unterminated_action(a_lineno, a_line, a_cptr);
1403
1404
	case ';':
1405
4399
		if (depth > 0)
1406
			goto loop;
1407
		fprintf(f, "\nbreak;\n");
1408
		free(a_line);
1409
		return;
1410
1411
	case '{':
1412
2032
		++depth;
1413
2032
		goto loop;
1414
1415
	case '}':
1416
2032
		if (--depth > 0)
1417
			goto loop;
1418
1501
		fprintf(f, "\nbreak;\n");
1419
1501
		free(a_line);
1420
1501
		return;
1421
1422
	case '\'':
1423
	case '"': {
1424
1148
		int s_lineno = lineno;
1425
1148
		char *s_line = dup_line();
1426
1148
		char *s_cptr = s_line + (cptr - line - 1);
1427
1428
		quote = c;
1429
1148
		for (;;) {
1430
16240
			c = (unsigned char) *cptr++;
1431
32480
			putc(c, f);
1432
16240
			if (c == quote) {
1433
1148
				free(s_line);
1434
				goto loop;
1435
			}
1436
15092
			if (c == '\n')
1437
				unterminated_string(s_lineno, s_line, s_cptr);
1438
15092
			if (c == '\\') {
1439
133
				c = (unsigned char) *cptr++;
1440
266
				putc(c, f);
1441
133
				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
212
		c = (unsigned char) *cptr;
1452
212
		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
212
		if (c == '*') {
1464
192
			int c_lineno = lineno;
1465
192
			char *c_line = dup_line();
1466
192
			char *c_cptr = c_line + (cptr - line - 1);
1467
1468
384
			putc('*', f);
1469
192
			++cptr;
1470
192
			for (;;) {
1471
5032
				c = (unsigned char) *cptr++;
1472
10064
				putc(c, f);
1473

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

22
	else if ((c == 'p' || c == 'P') &&
1508
11
	    ((c = cptr[2]) == 'r' || c == 'R') &&
1509
11
	    ((c = cptr[3]) == 'e' || c == 'E') &&
1510
11
	    ((c = cptr[4]) == 'c' || c == 'C') &&
1511
33
	    ((c = (unsigned char) cptr[5], !IS_IDENT(c))))
1512
		cptr += 5;
1513
	else
1514
		syntax_error(lineno, line, cptr);
1515
1516
11
	c = nextc();
1517
11
	if (isalpha(c) || c == '_' || c == '.' || c == '$')
1518
11
		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

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

30
	assert(i == ntokens && j == nsyms);
1672
1673
1766
	for (i = 1; i < ntokens; ++i)
1674
868
		v[i]->index = i;
1675
1676
15
	goal->index = start_symbol + 1;
1677
15
	k = start_symbol + 2;
1678
625
	while (++i < nsyms)
1679
595
		if (v[i] != goal) {
1680
580
			v[i]->index = k;
1681
580
			++k;
1682
580
		}
1683
15
	goal->value = 0;
1684
	k = 1;
1685
1220
	for (i = start_symbol + 1; i < nsyms; ++i) {
1686
595
		if (v[i] != goal) {
1687
580
			v[i]->value = k;
1688
580
			++k;
1689
580
		}
1690
	}
1691
1692
	k = 0;
1693
1766
	for (i = 1; i < ntokens; ++i) {
1694
868
		n = v[i]->value;
1695
868
		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
15
	if (v[1]->value == UNDEFINED)
1703
15
		v[1]->value = 256;
1704
1705
	j = 0;
1706
	n = 257;
1707
1736
	for (i = 2; i < ntokens; ++i) {
1708
853
		if (v[i]->value == UNDEFINED) {
1709

803
			while (j < k && n == symbol_value[j]) {
1710
				while (++j < k && n == symbol_value[j])
1711
					continue;
1712
				++n;
1713
			}
1714
803
			v[i]->value = n;
1715
803
			++n;
1716
803
		}
1717
	}
1718
1719
15
	symbol_name[0] = name_pool + 8;
1720
15
	symbol_value[0] = 0;
1721
15
	symbol_prec[0] = 0;
1722
15
	symbol_assoc[0] = TOKEN;
1723
1766
	for (i = 1; i < ntokens; ++i) {
1724
868
		symbol_name[i] = v[i]->name;
1725
868
		symbol_value[i] = v[i]->value;
1726
868
		symbol_prec[i] = v[i]->prec;
1727
868
		symbol_assoc[i] = v[i]->assoc;
1728
	}
1729
15
	symbol_name[start_symbol] = name_pool;
1730
15
	symbol_value[start_symbol] = -1;
1731
15
	symbol_prec[start_symbol] = 0;
1732
15
	symbol_assoc[start_symbol] = TOKEN;
1733
1220
	for (++i; i < nsyms; ++i) {
1734
595
		k = v[i]->index;
1735
595
		symbol_name[k] = v[i]->name;
1736
595
		symbol_value[k] = v[i]->value;
1737
595
		symbol_prec[k] = v[i]->prec;
1738
595
		symbol_assoc[k] = v[i]->assoc;
1739
	}
1740
1741
15
	free(v);
1742
15
}
1743
1744
1745
void
1746
pack_grammar(void)
1747
{
1748
	int i, j;
1749
	int assoc, pprec;
1750
1751
30
	ritem = reallocarray(NULL, nitems, sizeof(short));
1752
15
	if (ritem == NULL)
1753
		no_space();
1754
15
	rlhs = reallocarray(NULL, nrules, sizeof(short));
1755
15
	if (rlhs == NULL)
1756
		no_space();
1757
15
	rrhs = reallocarray(NULL, nrules + 1, sizeof(short));
1758
15
	if (rrhs == NULL)
1759
		no_space();
1760
15
	rprec = reallocarray(rprec, nrules, sizeof(short));
1761
15
	if (rprec == NULL)
1762
		no_space();
1763
15
	rassoc = realloc(rassoc, nrules);
1764
15
	if (rassoc == NULL)
1765
		no_space();
1766
1767
15
	ritem[0] = -1;
1768
15
	ritem[1] = goal->index;
1769
15
	ritem[2] = 0;
1770
15
	ritem[3] = -2;
1771
15
	rlhs[0] = 0;
1772
15
	rlhs[1] = 0;
1773
15
	rlhs[2] = start_symbol;
1774
15
	rrhs[0] = 0;
1775
15
	rrhs[1] = 0;
1776
15
	rrhs[2] = 1;
1777
1778
	j = 4;
1779
3730
	for (i = 3; i < nrules; ++i) {
1780
1850
		rlhs[i] = plhs[i]->index;
1781
1850
		rrhs[i] = j;
1782
		assoc = TOKEN;
1783
		pprec = 0;
1784
11962
		while (pitem[j]) {
1785
4131
			ritem[j] = pitem[j]->index;
1786
4131
			if (pitem[j]->class == TERM) {
1787
2124
				pprec = pitem[j]->prec;
1788
2124
				assoc = pitem[j]->assoc;
1789
2124
			}
1790
4131
			++j;
1791
		}
1792
1850
		ritem[j] = -i;
1793
1850
		++j;
1794
1850
		if (rprec[i] == UNDEFINED) {
1795
1786
			rprec[i] = pprec;
1796
1786
			rassoc[i] = assoc;
1797
1786
		}
1798
	}
1799
15
	rrhs[i] = j;
1800
1801
15
	free(plhs);
1802
15
	free(pitem);
1803
15
}
1804
1805
1806
void
1807
print_grammar(void)
1808
{
1809
	int i, j, k;
1810
	int spacing = 0;
1811
30
	FILE *f = verbose_file;
1812
1813
15
	if (!vflag)
1814
15
		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
15
}
1839
1840
1841
void
1842
reader(void)
1843
{
1844
30
	write_section(banner);
1845
15
	create_symbol_table();
1846
15
	read_declarations();
1847
15
	read_grammar();
1848
15
	free_symbol_table();
1849
15
	free_tags();
1850
15
	pack_names();
1851
15
	check_symbols();
1852
15
	pack_symbols();
1853
15
	pack_grammar();
1854
15
	free_symbols();
1855
15
	print_grammar();
1856
15
}