Bug Summary

File:src/usr.bin/yacc/reader.c
Warning:line 1702, column 6
Access to field 'value' results in a dereference of a null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name reader.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/yacc/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/yacc/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/yacc/reader.c
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 LINESIZE100 100
45
46char *cache;
47int cinc, cache_size;
48
49int ntags, tagmax;
50char **tag_table;
51
52char saw_eof, unionized;
53char *cptr, *line;
54int linesize;
55
56bucket *goal;
57int prec;
58int gensym;
59char last_was_action;
60
61int maxitems;
62bucket **pitem;
63
64int maxrules;
65bucket **plhs;
66
67int name_pool_size;
68char *name_pool;
69
70void cachec(int);
71void get_line(void);
72char *dup_line(void);
73void skip_comment(void);
74int nextc(void);
75int keyword(void);
76void copy_ident(void);
77void copy_text(void);
78void copy_union(void);
79bucket *get_literal(void);
80int is_reserved(char *);
81bucket *get_name(void);
82int get_number(void);
83char *get_tag(void);
84void declare_tokens(int);
85void declare_types(void);
86void declare_start(void);
87void handle_expect(void);
88void read_declarations(void);
89void initialize_grammar(void);
90void expand_items(void);
91void expand_rules(void);
92void advance_to_start(void);
93void start_rule(bucket *, int);
94void end_rule(void);
95void insert_empty_rule(void);
96void add_symbol(void);
97void copy_action(void);
98int mark_symbol(void);
99void read_grammar(void);
100void free_tags(void);
101void pack_names(void);
102void check_symbols(void);
103void pack_symbols(void);
104void pack_grammar(void);
105void print_grammar(void);
106
107char line_format[] = "#line %d \"%s\"\n";
108
109void
110cachec(int c)
111{
112 assert(cinc >= 0)((cinc >= 0) ? (void)0 : __assert2("/usr/src/usr.bin/yacc/reader.c"
, 112, __func__, "cinc >= 0"))
;
113 if (cinc >= cache_size) {
114 cache_size += 256;
115 cache = realloc(cache, cache_size);
116 if (cache == NULL((void *)0))
117 no_space();
118 }
119 cache[cinc] = c;
120 ++cinc;
121}
122
123
124void
125get_line(void)
126{
127 FILE *f = input_file;
128 int c, i;
129
130 if (saw_eof || (c = getc(f)(!__isthreaded ? (--(f)->_r < 0 ? __srget(f) : (int)(*(
f)->_p++)) : (getc)(f))
) == EOF(-1)) {
131 if (line) {
132 free(line);
133 line = 0;
134 }
135 cptr = 0;
136 saw_eof = 1;
137 return;
138 }
139 if (line == NULL((void *)0) || linesize != (LINESIZE100 + 1)) {
140 free(line);
141 linesize = LINESIZE100 + 1;
142 line = malloc(linesize);
143 if (line == NULL((void *)0))
144 no_space();
145 }
146 i = 0;
147 ++lineno;
148 for (;;) {
149 line[i] = c;
150 if (c == '\n') {
151 cptr = line;
152 return;
153 }
154 if (++i >= linesize) {
155 linesize += LINESIZE100;
156 line = realloc(line, linesize);
157 if (line == NULL((void *)0))
158 no_space();
159 }
160 c = getc(f)(!__isthreaded ? (--(f)->_r < 0 ? __srget(f) : (int)(*(
f)->_p++)) : (getc)(f))
;
161 if (c == EOF(-1)) {
162 line[i] = '\n';
163 saw_eof = 1;
164 cptr = line;
165 return;
166 }
167 }
168}
169
170
171char *
172dup_line(void)
173{
174 char *p, *s, *t;
175
176 if (line == NULL((void *)0))
177 return (0);
178 s = line;
179 while (*s != '\n')
180 ++s;
181 p = malloc(s - line + 1);
182 if (p == NULL((void *)0))
183 no_space();
184
185 s = line;
186 t = p;
187 while ((*t++ = *s++) != '\n')
188 continue;
189 return (p);
190}
191
192
193void
194skip_comment(void)
195{
196 char *s;
197 int st_lineno = lineno;
198 char *st_line = dup_line();
199 char *st_cptr = st_line + (cptr - line);
200
201 s = cptr + 2;
202 for (;;) {
203 if (*s == '*' && s[1] == '/') {
204 cptr = s + 2;
205 free(st_line);
206 return;
207 }
208 if (*s == '\n') {
209 get_line();
210 if (line == NULL((void *)0))
211 unterminated_comment(st_lineno, st_line, st_cptr);
212 s = cptr;
213 } else
214 ++s;
215 }
216}
217
218
219int
220nextc(void)
221{
222 char *s;
223
224 if (line == NULL((void *)0)) {
225 get_line();
226 if (line == NULL((void *)0))
227 return (EOF(-1));
228 }
229 s = cptr;
230 for (;;) {
231 switch (*s) {
232 case '\n':
233 get_line();
234 if (line == NULL((void *)0))
235 return (EOF(-1));
236 s = cptr;
237 break;
238
239 case ' ':
240 case '\t':
241 case '\f':
242 case '\r':
243 case '\v':
244 case ',':
245 case ';':
246 ++s;
247 break;
248
249 case '\\':
250 cptr = s;
251 return ('%');
252
253 case '/':
254 if (s[1] == '*') {
255 cptr = s;
256 skip_comment();
257 s = cptr;
258 break;
259 } else if (s[1] == '/') {
260 get_line();
261 if (line == NULL((void *)0))
262 return (EOF(-1));
263 s = cptr;
264 break;
265 }
266 /* fall through */
267
268 default:
269 cptr = s;
270 return ((unsigned char) *s);
271 }
272 }
273}
274
275
276int
277keyword(void)
278{
279 int c;
280 char *t_cptr = cptr;
281
282 c = (unsigned char) *++cptr;
283 if (isalpha(c)) {
284 cinc = 0;
285 for (;;) {
286 if (isalpha(c)) {
287 if (isupper(c))
288 c = tolower(c);
289 cachec(c);
290 } else if (isdigit(c) || c == '_' || c == '.' || c == '$')
291 cachec(c);
292 else
293 break;
294 c = (unsigned char) *++cptr;
295 }
296 cachec(NUL'\0');
297
298 if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0)
299 return (TOKEN0);
300 if (strcmp(cache, "type") == 0)
301 return (TYPE6);
302 if (strcmp(cache, "left") == 0)
303 return (LEFT1);
304 if (strcmp(cache, "right") == 0)
305 return (RIGHT2);
306 if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0)
307 return (NONASSOC3);
308 if (strcmp(cache, "start") == 0)
309 return (START7);
310 if (strcmp(cache, "union") == 0)
311 return (UNION8);
312 if (strcmp(cache, "ident") == 0)
313 return (IDENT9);
314 if (strcmp(cache, "expect") == 0)
315 return (EXPECT10);
316 } else {
317 ++cptr;
318 if (c == '{')
319 return (TEXT5);
320 if (c == '%' || c == '\\')
321 return (MARK4);
322 if (c == '<')
323 return (LEFT1);
324 if (c == '>')
325 return (RIGHT2);
326 if (c == '0')
327 return (TOKEN0);
328 if (c == '2')
329 return (NONASSOC3);
330 }
331 syntax_error(lineno, line, t_cptr);
332 /* NOTREACHED */
333 return (0);
334}
335
336
337void
338copy_ident(void)
339{
340 int c;
341 FILE *f = output_file;
342
343 c = nextc();
344 if (c == EOF(-1))
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)(!__isthreaded ? __sputc(c, f) : (putc)(c, f));
357 if (c == '"') {
358 putc('\n', f)(!__isthreaded ? __sputc('\n', f) : (putc)('\n', f));
359 ++cptr;
360 return;
361 }
362 }
363}
364
365
366void
367copy_text(void)
368{
369 int c;
370 int quote;
371 FILE *f = text_file;
372 int need_newline = 0;
373 int t_lineno = lineno;
374 char *t_line = dup_line();
375 char *t_cptr = t_line + (cptr - line - 2);
376
377 if (*cptr == '\n') {
378 get_line();
379 if (line == NULL((void *)0))
380 unterminated_text(t_lineno, t_line, t_cptr);
381 }
382 if (!lflag)
383 fprintf(f, line_format, lineno, input_file_name);
384
385loop:
386 c = (unsigned char) *cptr++;
387 switch (c) {
388 case '\n':
389next_line:
390 putc('\n', f)(!__isthreaded ? __sputc('\n', f) : (putc)('\n', f));
391 need_newline = 0;
392 get_line();
393 if (line)
394 goto loop;
395 unterminated_text(t_lineno, t_line, t_cptr);
396
397 case '\'':
398 case '"': {
399 int s_lineno = lineno;
400 char *s_line = dup_line();
401 char *s_cptr = s_line + (cptr - line - 1);
402
403 quote = c;
404 putc(c, f)(!__isthreaded ? __sputc(c, f) : (putc)(c, f));
405 for (;;) {
406 c = (unsigned char) *cptr++;
407 putc(c, f)(!__isthreaded ? __sputc(c, f) : (putc)(c, f));
408 if (c == quote) {
409 need_newline = 1;
410 free(s_line);
411 goto loop;
412 }
413 if (c == '\n')
414 unterminated_string(s_lineno, s_line, s_cptr);
415 if (c == '\\') {
416 c = (unsigned char) *cptr++;
417 putc(c, f)(!__isthreaded ? __sputc(c, f) : (putc)(c, f));
418 if (c == '\n') {
419 get_line();
420 if (line == NULL((void *)0))
421 unterminated_string(s_lineno, s_line, s_cptr);
422 }
423 }
424 }
425 }
426
427 case '/':
428 putc(c, f)(!__isthreaded ? __sputc(c, f) : (putc)(c, f));
429 need_newline = 1;
430 c = (unsigned char) *cptr;
431 if (c == '/') {
432 putc('*', f)(!__isthreaded ? __sputc('*', f) : (putc)('*', f));
433 while ((c = (unsigned char) *++cptr) != '\n') {
434 if (c == '*' && cptr[1] == '/')
435 fprintf(f, "* ");
436 else
437 putc(c, f)(!__isthreaded ? __sputc(c, f) : (putc)(c, f));
438 }
439 fprintf(f, "*/");
440 goto next_line;
441 }
442 if (c == '*') {
443 int c_lineno = lineno;
444 char *c_line = dup_line();
445 char *c_cptr = c_line + (cptr - line - 1);
446
447 putc('*', f)(!__isthreaded ? __sputc('*', f) : (putc)('*', f));
448 ++cptr;
449 for (;;) {
450 c = (unsigned char) *cptr++;
451 putc(c, f)(!__isthreaded ? __sputc(c, f) : (putc)(c, f));
452 if (c == '*' && *cptr == '/') {
453 putc('/', f)(!__isthreaded ? __sputc('/', f) : (putc)('/', f));
454 ++cptr;
455 free(c_line);
456 goto loop;
457 }
458 if (c == '\n') {
459 get_line();
460 if (line == NULL((void *)0))
461 unterminated_comment(c_lineno, c_line, c_cptr);
462 }
463 }
464 }
465 need_newline = 1;
466 goto loop;
467
468 case '%':
469 case '\\':
470 if (*cptr == '}') {
471 if (need_newline)
472 putc('\n', f)(!__isthreaded ? __sputc('\n', f) : (putc)('\n', f));
473 ++cptr;
474 free(t_line);
475 return;
476 }
477 /* fall through */
478
479 default:
480 putc(c, f)(!__isthreaded ? __sputc(c, f) : (putc)(c, f));
481 need_newline = 1;
482 goto loop;
483 }
484}
485
486
487void
488copy_union(void)
489{
490 int c, quote, depth;
491 int u_lineno = lineno;
492 char *u_line = dup_line();
493 char *u_cptr = u_line + (cptr - line - 6);
494
495 if (unionized)
496 over_unionized(cptr - 6);
497 unionized = 1;
498
499 if (!lflag)
500 fprintf(text_file, line_format, lineno, input_file_name);
501
502 fprintf(text_file, "#ifndef YYSTYPE_DEFINED\n");
503 fprintf(text_file, "#define YYSTYPE_DEFINED\n");
504 fprintf(text_file, "typedef union");
505 if (dflag) {
506 fprintf(union_file, "#ifndef YYSTYPE_DEFINED\n");
507 fprintf(union_file, "#define YYSTYPE_DEFINED\n");
508 fprintf(union_file, "typedef union");
509 }
510
511 depth = 0;
512loop:
513 c = (unsigned char) *cptr++;
514 putc(c, text_file)(!__isthreaded ? __sputc(c, text_file) : (putc)(c, text_file)
)
;
515 if (dflag)
516 putc(c, union_file)(!__isthreaded ? __sputc(c, union_file) : (putc)(c, union_file
))
;
517 switch (c) {
518 case '\n':
519next_line:
520 get_line();
521 if (line == NULL((void *)0))
522 unterminated_union(u_lineno, u_line, u_cptr);
523 goto loop;
524
525 case '{':
526 ++depth;
527 goto loop;
528
529 case '}':
530 if (--depth == 0) {
531 fprintf(text_file, " YYSTYPE;\n");
532 fprintf(text_file, "#endif /* YYSTYPE_DEFINED */\n");
533 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)(!__isthreaded ? __sputc(c, text_file) : (putc)(c, text_file)
)
;
548 if (dflag)
549 putc(c, union_file)(!__isthreaded ? __sputc(c, union_file) : (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)(!__isthreaded ? __sputc(c, text_file) : (putc)(c, text_file)
)
;
559 if (dflag)
560 putc(c, union_file)(!__isthreaded ? __sputc(c, union_file) : (putc)(c, union_file
))
;
561 if (c == '\n') {
562 get_line();
563 if (line == NULL((void *)0))
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)(!__isthreaded ? __sputc('*', text_file) : (putc)('*', text_file
))
;
575 if (dflag)
576 putc('*', union_file)(!__isthreaded ? __sputc('*', union_file) : (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)(!__isthreaded ? __sputc(c, text_file) : (putc)(c, text_file)
)
;
584 if (dflag)
585 putc(c, union_file)(!__isthreaded ? __sputc(c, union_file) : (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)(!__isthreaded ? __sputc('*', text_file) : (putc)('*', text_file
))
;
599 if (dflag)
600 putc('*', union_file)(!__isthreaded ? __sputc('*', union_file) : (putc)('*', union_file
))
;
601 ++cptr;
602 for (;;) {
603 c = (unsigned char) *cptr++;
604 putc(c, text_file)(!__isthreaded ? __sputc(c, text_file) : (putc)(c, text_file)
)
;
605 if (dflag)
606 putc(c, union_file)(!__isthreaded ? __sputc(c, union_file) : (putc)(c, union_file
))
;
607 if (c == '*' && *cptr == '/') {
608 putc('/', text_file)(!__isthreaded ? __sputc('/', text_file) : (putc)('/', text_file
))
;
609 if (dflag)
610 putc('/', union_file)(!__isthreaded ? __sputc('/', union_file) : (putc)('/', union_file
))
;
611 ++cptr;
612 free(c_line);
613 goto loop;
614 }
615 if (c == '\n') {
616 get_line();
617 if (line == NULL((void *)0))
618 unterminated_comment(c_lineno,
619 c_line, c_cptr);
620 }
621 }
622 }
623 goto loop;
624
625 default:
626 goto loop;
627 }
628}
629
630
631bucket *
632get_literal(void)
633{
634 int c, quote, i, n;
635 char *s;
636 bucket *bp;
637 int s_lineno = lineno;
638 char *s_line = dup_line();
639 char *s_cptr = s_line + (cptr - line);
640
641 quote = (unsigned char) *cptr++;
642 cinc = 0;
643 for (;;) {
644 c = (unsigned char) *cptr++;
645 if (c == quote)
646 break;
647 if (c == '\n')
648 unterminated_string(s_lineno, s_line, s_cptr);
649 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((void *)0))
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 > MAXCHAR255)
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 > MAXCHAR255)
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 cachec(c);
709 }
710 free(s_line);
711
712 n = cinc;
713 s = malloc(n);
714 if (s == NULL((void *)0))
715 no_space();
716
717 memcpy(s, cache, n);
718
719 cinc = 0;
720 if (n == 1)
721 cachec('\'');
722 else
723 cachec('"');
724
725 for (i = 0; i < n; ++i) {
726 c = ((unsigned char *) s)[i];
727 if (c == '\\' || c == cache[0]) {
728 cachec('\\');
729 cachec(c);
730 } else if (isprint(c))
731 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 if (n == 1)
766 cachec('\'');
767 else
768 cachec('"');
769
770 cachec(NUL'\0');
771 bp = lookup(cache);
772 bp->class = TERM1;
773 if (n == 1 && bp->value == UNDEFINED(-1))
774 bp->value = *(unsigned char *) s;
775 free(s);
776
777 return (bp);
778}
779
780
781int
782is_reserved(char *name)
783{
784 char *s;
785
786 if (strcmp(name, ".") == 0 ||
787 strcmp(name, "$accept") == 0 ||
788 strcmp(name, "$end") == 0)
789 return (1);
790
791 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'\0')
796 return (1);
797 }
798 return (0);
799}
800
801
802bucket *
803get_name(void)
804{
805 int c;
806
807 cinc = 0;
808 for (c = (unsigned char) *cptr; IS_IDENT(c)(isalnum(c) || (c) == '_' || (c) == '.' || (c) == '$'); c = (unsigned char) *++cptr)
809 cachec(c);
810 cachec(NUL'\0');
811
812 if (is_reserved(cache))
813 used_reserved(cache);
814
815 return (lookup(cache));
816}
817
818
819int
820get_number(void)
821{
822 unsigned long ul;
823 char *p;
824
825 ul = strtoul(cptr, &p, 10);
826 if (ul > INT_MAX2147483647)
827 syntax_error(lineno, line, cptr);
828 cptr = p;
829 return (ul);
830}
831
832
833char *
834get_tag(void)
835{
836 int c, i;
837 char *s;
838 int t_lineno = lineno;
839 char *t_line = dup_line();
840 char *t_cptr = t_line + (cptr - line);
841
842 ++cptr;
843 c = nextc();
844 if (c == EOF(-1))
845 unexpected_EOF();
846 if (!isalpha(c) && c != '_' && c != '$')
847 illegal_tag(t_lineno, t_line, t_cptr);
848
849 cinc = 0;
850 do {
851 cachec(c);
852 c = (unsigned char) *++cptr;
853 } while (IS_IDENT(c)(isalnum(c) || (c) == '_' || (c) == '.' || (c) == '$'));
854 cachec(NUL'\0');
855
856 c = nextc();
857 if (c == EOF(-1))
858 unexpected_EOF();
859 if (c != '>')
860 illegal_tag(t_lineno, t_line, t_cptr);
861 free(t_line);
862 ++cptr;
863
864 for (i = 0; i < ntags; ++i) {
865 if (strcmp(cache, tag_table[i]) == 0)
866 return (tag_table[i]);
867 }
868
869 if (ntags >= tagmax) {
870 tagmax += 16;
871 tag_table = reallocarray(tag_table, tagmax, sizeof(char *));
872 if (tag_table == NULL((void *)0))
873 no_space();
874 }
875 s = malloc(cinc);
876 if (s == NULL((void *)0))
877 no_space();
878 strlcpy(s, cache, cinc);
879 tag_table[ntags] = s;
880 ++ntags;
881 return (s);
882}
883
884
885void
886declare_tokens(int assoc)
887{
888 int c;
889 bucket *bp;
890 int value;
891 char *tag = 0;
892
893 if (assoc != TOKEN0)
894 ++prec;
895
896 c = nextc();
897 if (c == EOF(-1))
898 unexpected_EOF();
899 if (c == '<') {
900 tag = get_tag();
901 c = nextc();
902 if (c == EOF(-1))
903 unexpected_EOF();
904 }
905 for (;;) {
906 if (isalpha(c) || c == '_' || c == '.' || c == '$')
907 bp = get_name();
908 else if (c == '\'' || c == '"')
909 bp = get_literal();
910 else
911 return;
912
913 if (bp == goal)
914 tokenized_start(bp->name);
915 bp->class = TERM1;
916
917 if (tag) {
918 if (bp->tag && tag != bp->tag)
919 retyped_warning(bp->name);
920 bp->tag = tag;
921 }
922 if (assoc != TOKEN0) {
923 if (bp->prec && prec != bp->prec)
924 reprec_warning(bp->name);
925 bp->assoc = assoc;
926 bp->prec = prec;
927 }
928 c = nextc();
929 if (c == EOF(-1))
930 unexpected_EOF();
931 if (isdigit(c)) {
932 value = get_number();
933 if (bp->value != UNDEFINED(-1) && value != bp->value)
934 revalued_warning(bp->name);
935 bp->value = value;
936 c = nextc();
937 if (c == EOF(-1))
938 unexpected_EOF();
939 }
940 }
941}
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 */
948static void
949declare_expect(int assoc)
950{
951 int c;
952
953 if (assoc != EXPECT10)
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(-1))
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(-1))
978 unexpected_EOF();
979 }
980 }
981}
982
983
984void
985declare_types(void)
986{
987 int c;
988 bucket *bp;
989 char *tag;
990
991 c = nextc();
992 if (c == EOF(-1))
993 unexpected_EOF();
994 if (c != '<')
995 syntax_error(lineno, line, cptr);
996 tag = get_tag();
997
998 for (;;) {
999 c = nextc();
1000 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1001 bp = get_name();
1002 else if (c == '\'' || c == '"')
1003 bp = get_literal();
1004 else
1005 return;
1006
1007 if (bp->tag && tag != bp->tag)
1008 retyped_warning(bp->name);
1009 bp->tag = tag;
1010 }
1011}
1012
1013
1014void
1015declare_start(void)
1016{
1017 int c;
1018 bucket *bp;
1019
1020 c = nextc();
1021 if (c == EOF(-1))
1022 unexpected_EOF();
1023 if (!isalpha(c) && c != '_' && c != '.' && c != '$')
1024 syntax_error(lineno, line, cptr);
1025 bp = get_name();
1026 if (bp->class == TERM1)
1027 terminal_start(bp->name);
1028 if (goal && goal != bp)
1029 restarted_warning();
1030 goal = bp;
1031}
1032
1033
1034void
1035read_declarations(void)
1036{
1037 int c, k;
1038
1039 cache_size = 256;
1040 cache = malloc(cache_size);
1041 if (cache == NULL((void *)0))
1042 no_space();
1043
1044 for (;;) {
1045 c = nextc();
1046 if (c == EOF(-1))
1047 unexpected_EOF();
1048 if (c != '%')
1049 syntax_error(lineno, line, cptr);
1050 switch (k = keyword()) {
1051 case MARK4:
1052 return;
1053
1054 case IDENT9:
1055 copy_ident();
1056 break;
1057
1058 case TEXT5:
1059 copy_text();
1060 break;
1061
1062 case UNION8:
1063 copy_union();
1064 break;
1065
1066 case TOKEN0:
1067 case LEFT1:
1068 case RIGHT2:
1069 case NONASSOC3:
1070 declare_tokens(k);
1071 break;
1072
1073 case EXPECT10:
1074 declare_expect(k);
1075 break;
1076
1077 case TYPE6:
1078 declare_types();
1079 break;
1080
1081 case START7:
1082 declare_start();
1083 break;
1084 }
1085 }
1086}
1087
1088
1089void
1090initialize_grammar(void)
1091{
1092 nitems = 4;
1093 maxitems = 300;
1094 pitem = calloc(maxitems, sizeof(bucket *));
1095 if (pitem == NULL((void *)0))
1096 no_space();
1097
1098 nrules = 3;
1099 maxrules = 100;
1100 plhs = reallocarray(NULL((void *)0), maxrules, sizeof(bucket *));
1101 if (plhs == NULL((void *)0))
1102 no_space();
1103 plhs[0] = 0;
1104 plhs[1] = 0;
1105 plhs[2] = 0;
1106 rprec = reallocarray(NULL((void *)0), maxrules, sizeof(short));
1107 if (rprec == NULL((void *)0))
1108 no_space();
1109 rprec[0] = 0;
1110 rprec[1] = 0;
1111 rprec[2] = 0;
1112 rassoc = reallocarray(NULL((void *)0), maxrules, sizeof(char));
1113 if (rassoc == NULL((void *)0))
1114 no_space();
1115 rassoc[0] = TOKEN0;
1116 rassoc[1] = TOKEN0;
1117 rassoc[2] = TOKEN0;
1118}
1119
1120
1121void
1122expand_items(void)
1123{
1124 int olditems = maxitems;
1125
1126 maxitems += 300;
1127 pitem = reallocarray(pitem, maxitems, sizeof(bucket *));
1128 if (pitem == NULL((void *)0))
1129 no_space();
1130 memset(pitem + olditems, 0, (maxitems - olditems) * sizeof(bucket *));
1131}
1132
1133
1134void
1135expand_rules(void)
1136{
1137 maxrules += 100;
1138 plhs = reallocarray(plhs, maxrules, sizeof(bucket *));
1139 if (plhs == NULL((void *)0))
1140 no_space();
1141 rprec = reallocarray(rprec, maxrules, sizeof(short));
1142 if (rprec == NULL((void *)0))
1143 no_space();
1144 rassoc = reallocarray(rassoc, maxrules, sizeof(char));
1145 if (rassoc == NULL((void *)0))
1146 no_space();
1147}
1148
1149
1150void
1151advance_to_start(void)
1152{
1153 int c;
1154 bucket *bp;
1155 char *s_cptr;
1156 int s_lineno;
1157
1158 for (;;) {
1159 c = nextc();
1160 if (c != '%')
1161 break;
1162 s_cptr = cptr;
1163 switch (keyword()) {
1164 case MARK4:
1165 no_grammar();
1166
1167 case TEXT5:
1168 copy_text();
1169 break;
1170
1171 case START7:
1172 declare_start();
1173 break;
1174
1175 default:
1176 syntax_error(lineno, line, s_cptr);
1177 }
1178 }
1179
1180 c = nextc();
1181 if (!isalpha(c) && c != '_' && c != '.' && c != '_')
1182 syntax_error(lineno, line, cptr);
1183 bp = get_name();
1184 if (goal == NULL((void *)0)) {
1185 if (bp->class == TERM1)
1186 terminal_start(bp->name);
1187 goal = bp;
1188 }
1189 s_lineno = lineno;
1190 c = nextc();
1191 if (c == EOF(-1))
1192 unexpected_EOF();
1193 if (c != ':')
1194 syntax_error(lineno, line, cptr);
1195 start_rule(bp, s_lineno);
1196 ++cptr;
1197}
1198
1199
1200void
1201start_rule(bucket * bp, int s_lineno)
1202{
1203 if (bp->class == TERM1)
1204 terminal_lhs(s_lineno);
1205 bp->class = NONTERM2;
1206 if (nrules >= maxrules)
1207 expand_rules();
1208 plhs[nrules] = bp;
1209 rprec[nrules] = UNDEFINED(-1);
1210 rassoc[nrules] = TOKEN0;
1211}
1212
1213
1214void
1215end_rule(void)
1216{
1217 int i;
1218
1219 if (!last_was_action && plhs[nrules]->tag) {
1220 for (i = nitems - 1; pitem[i]; --i)
1221 continue;
1222 if (i == maxitems - 1 || pitem[i + 1] == 0 ||
1223 pitem[i + 1]->tag != plhs[nrules]->tag)
1224 default_action_warning();
1225 }
1226 last_was_action = 0;
1227 if (nitems >= maxitems)
1228 expand_items();
1229 pitem[nitems] = 0;
1230 ++nitems;
1231 ++nrules;
1232}
1233
1234
1235void
1236insert_empty_rule(void)
1237{
1238 bucket *bp, **bpp;
1239
1240 assert(cache)((cache) ? (void)0 : __assert2("/usr/src/usr.bin/yacc/reader.c"
, 1240, __func__, "cache"))
;
1241 snprintf(cache, cache_size, "$$%d", ++gensym);
1242 bp = make_bucket(cache);
1243 last_symbol->next = bp;
1244 last_symbol = bp;
1245 bp->tag = plhs[nrules]->tag;
1246 bp->class = NONTERM2;
1247
1248 if ((nitems += 2) > maxitems)
1249 expand_items();
1250 bpp = pitem + nitems - 1;
1251 *bpp-- = bp;
1252 while ((bpp[0] = bpp[-1]))
1253 --bpp;
1254
1255 if (++nrules >= maxrules)
1256 expand_rules();
1257 plhs[nrules] = plhs[nrules - 1];
1258 plhs[nrules - 1] = bp;
1259 rprec[nrules] = rprec[nrules - 1];
1260 rprec[nrules - 1] = 0;
1261 rassoc[nrules] = rassoc[nrules - 1];
1262 rassoc[nrules - 1] = TOKEN0;
1263}
1264
1265
1266void
1267add_symbol(void)
1268{
1269 int c;
1270 bucket *bp;
1271 int s_lineno = lineno;
1272
1273 c = (unsigned char) *cptr;
1274 if (c == '\'' || c == '"')
1275 bp = get_literal();
1276 else
1277 bp = get_name();
1278
1279 c = nextc();
1280 if (c == ':') {
1281 end_rule();
1282 start_rule(bp, s_lineno);
1283 ++cptr;
1284 return;
1285 }
1286 if (last_was_action)
1287 insert_empty_rule();
1288 last_was_action = 0;
1289
1290 if (++nitems > maxitems)
1291 expand_items();
1292 pitem[nitems - 1] = bp;
1293}
1294
1295
1296void
1297copy_action(void)
1298{
1299 int c, i, n, depth, quote;
1300 char *tag;
1301 FILE *f = action_file;
1302 int a_lineno = lineno;
1303 char *a_line = dup_line();
1304 char *a_cptr = a_line + (cptr - line);
1305
1306 if (last_was_action)
1307 insert_empty_rule();
1308 last_was_action = 1;
1309
1310 fprintf(f, "case %d:\n", nrules - 2);
1311 if (!lflag)
1312 fprintf(f, line_format, lineno, input_file_name);
1313 if (*cptr == '=')
1314 ++cptr;
1315
1316 n = 0;
1317 for (i = nitems - 1; pitem[i]; --i)
1318 ++n;
1319
1320 depth = 0;
1321loop:
1322 c = (unsigned char) *cptr;
1323 if (c == '$') {
1324 if (cptr[1] == '<') {
1325 int d_lineno = lineno;
1326 char *d_line = dup_line();
1327 char *d_cptr = d_line + (cptr - line);
1328
1329 ++cptr;
1330 tag = get_tag();
1331 c = (unsigned char) *cptr;
1332 if (c == '$') {
1333 fprintf(f, "yyval.%s", tag);
1334 ++cptr;
1335 free(d_line);
1336 goto loop;
1337 } else if (isdigit(c)) {
1338 i = get_number();
1339 if (i > n)
1340 dollar_warning(d_lineno, i);
1341 fprintf(f, "yyvsp[%d].%s", i - n, tag);
1342 free(d_line);
1343 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 } else if (cptr[1] == '$') {
1353 if (ntags) {
1354 tag = plhs[nrules]->tag;
1355 if (tag == NULL((void *)0))
1356 untyped_lhs();
1357 fprintf(f, "yyval.%s", tag);
1358 } else
1359 fprintf(f, "yyval");
1360 cptr += 2;
1361 goto loop;
1362 } else if (isdigit((unsigned char) cptr[1])) {
1363 ++cptr;
1364 i = get_number();
1365 if (ntags) {
1366 if (i <= 0 || i > n)
1367 unknown_rhs(i);
1368 tag = pitem[nitems + i - n - 1]->tag;
1369 if (tag == NULL((void *)0))
1370 untyped_rhs(i, pitem[nitems + i - n - 1]->name);
1371 fprintf(f, "yyvsp[%d].%s", i - n, tag);
1372 } 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 if (isalpha(c) || c == '_' || c == '$') {
1388 do {
1389 putc(c, f)(!__isthreaded ? __sputc(c, f) : (putc)(c, f));
1390 c = (unsigned char) *++cptr;
1391 } while (isalnum(c) || c == '_' || c == '$');
1392 goto loop;
1393 }
1394 putc(c, f)(!__isthreaded ? __sputc(c, f) : (putc)(c, f));
1395 ++cptr;
1396 switch (c) {
1397 case '\n':
1398next_line:
1399 get_line();
1400 if (line)
1401 goto loop;
1402 unterminated_action(a_lineno, a_line, a_cptr);
1403
1404 case ';':
1405 if (depth > 0)
1406 goto loop;
1407 fprintf(f, "\nbreak;\n");
1408 free(a_line);
1409 return;
1410
1411 case '{':
1412 ++depth;
1413 goto loop;
1414
1415 case '}':
1416 if (--depth > 0)
1417 goto loop;
1418 fprintf(f, "\nbreak;\n");
1419 free(a_line);
1420 return;
1421
1422 case '\'':
1423 case '"': {
1424 int s_lineno = lineno;
1425 char *s_line = dup_line();
1426 char *s_cptr = s_line + (cptr - line - 1);
1427
1428 quote = c;
1429 for (;;) {
1430 c = (unsigned char) *cptr++;
1431 putc(c, f)(!__isthreaded ? __sputc(c, f) : (putc)(c, f));
1432 if (c == quote) {
1433 free(s_line);
1434 goto loop;
1435 }
1436 if (c == '\n')
1437 unterminated_string(s_lineno, s_line, s_cptr);
1438 if (c == '\\') {
1439 c = (unsigned char) *cptr++;
1440 putc(c, f)(!__isthreaded ? __sputc(c, f) : (putc)(c, f));
1441 if (c == '\n') {
1442 get_line();
1443 if (line == NULL((void *)0))
1444 unterminated_string(s_lineno, s_line, s_cptr);
1445 }
1446 }
1447 }
1448 }
1449
1450 case '/':
1451 c = (unsigned char) *cptr;
1452 if (c == '/') {
1453 putc('*', f)(!__isthreaded ? __sputc('*', f) : (putc)('*', f));
1454 while ((c = (unsigned char) *++cptr) != '\n') {
1455 if (c == '*' && cptr[1] == '/')
1456 fprintf(f, "* ");
1457 else
1458 putc(c, f)(!__isthreaded ? __sputc(c, f) : (putc)(c, f));
1459 }
1460 fprintf(f, "*/\n");
1461 goto next_line;
1462 }
1463 if (c == '*') {
1464 int c_lineno = lineno;
1465 char *c_line = dup_line();
1466 char *c_cptr = c_line + (cptr - line - 1);
1467
1468 putc('*', f)(!__isthreaded ? __sputc('*', f) : (putc)('*', f));
1469 ++cptr;
1470 for (;;) {
1471 c = (unsigned char) *cptr++;
1472 putc(c, f)(!__isthreaded ? __sputc(c, f) : (putc)(c, f));
1473 if (c == '*' && *cptr == '/') {
1474 putc('/', f)(!__isthreaded ? __sputc('/', f) : (putc)('/', f));
1475 ++cptr;
1476 free(c_line);
1477 goto loop;
1478 }
1479 if (c == '\n') {
1480 get_line();
1481 if (line == NULL((void *)0))
1482 unterminated_comment(c_lineno, c_line, c_cptr);
1483 }
1484 }
1485 }
1486 goto loop;
1487
1488 default:
1489 goto loop;
1490 }
1491}
1492
1493
1494int
1495mark_symbol(void)
1496{
1497 int c;
1498 bucket *bp = NULL((void *)0);
1499
1500 c = (unsigned char) cptr[1];
1501 if (c == '%' || c == '\\') {
1502 cptr += 2;
1503 return (1);
1504 }
1505 if (c == '=')
1506 cptr += 2;
1507 else if ((c == 'p' || c == 'P') &&
1508 ((c = cptr[2]) == 'r' || c == 'R') &&
1509 ((c = cptr[3]) == 'e' || c == 'E') &&
1510 ((c = cptr[4]) == 'c' || c == 'C') &&
1511 ((c = (unsigned char) cptr[5], !IS_IDENT(c)(isalnum(c) || (c) == '_' || (c) == '.' || (c) == '$'))))
1512 cptr += 5;
1513 else
1514 syntax_error(lineno, line, cptr);
1515
1516 c = nextc();
1517 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1518 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 if (rprec[nrules] != UNDEFINED(-1) && bp->prec != rprec[nrules])
1527 prec_redeclared();
1528
1529 rprec[nrules] = bp->prec;
1530 rassoc[nrules] = bp->assoc;
1531 return (0);
1532}
1533
1534
1535void
1536read_grammar(void)
1537{
1538 int c;
1539
1540 initialize_grammar();
1541 advance_to_start();
1542
1543 for (;;) {
1544 c = nextc();
1545 if (c == EOF(-1))
1546 break;
1547 if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' ||
1548 c == '"')
1549 add_symbol();
1550 else if (c == '{' || c == '=')
1551 copy_action();
1552 else if (c == '|') {
1553 end_rule();
1554 start_rule(plhs[nrules - 1], 0);
1555 ++cptr;
1556 } else if (c == '%') {
1557 if (mark_symbol())
1558 break;
1559 } else
1560 syntax_error(lineno, line, cptr);
1561 }
1562 end_rule();
1563}
1564
1565
1566void
1567free_tags(void)
1568{
1569 int i;
1570
1571 if (tag_table == NULL((void *)0))
1572 return;
1573
1574 for (i = 0; i < ntags; ++i) {
1575 assert(tag_table[i])((tag_table[i]) ? (void)0 : __assert2("/usr/src/usr.bin/yacc/reader.c"
, 1575, __func__, "tag_table[i]"))
;
1576 free(tag_table[i]);
1577 }
1578 free(tag_table);
1579}
1580
1581
1582void
1583pack_names(void)
1584{
1585 bucket *bp;
1586 char *p, *s, *t;
1587
1588 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
1589 for (bp = first_symbol; bp; bp = bp->next)
1590 name_pool_size += strlen(bp->name) + 1;
1591 name_pool = malloc(name_pool_size);
1592 if (name_pool == NULL((void *)0))
1593 no_space();
1594
1595 strlcpy(name_pool, "$accept", name_pool_size);
1596 strlcpy(name_pool + 8, "$end", name_pool_size - 8);
1597 t = name_pool + 13;
1598 for (bp = first_symbol; bp; bp = bp->next) {
1599 p = t;
1600 s = bp->name;
1601 while ((*t++ = *s++))
1602 continue;
1603 free(bp->name);
1604 bp->name = p;
1605 }
1606}
1607
1608
1609void
1610check_symbols(void)
1611{
1612 bucket *bp;
1613
1614 if (goal->class == UNKNOWN0)
1615 undefined_goal(goal->name);
1616
1617 for (bp = first_symbol; bp; bp = bp->next) {
1618 if (bp->class == UNKNOWN0) {
1619 undefined_symbol_warning(bp->name);
1620 bp->class = TERM1;
1621 }
1622 }
1623}
1624
1625
1626void
1627pack_symbols(void)
1628{
1629 bucket *bp;
1630 bucket **v;
1631 int i, j, k, n;
1632
1633 nsyms = 2;
1634 ntokens = 1;
1635 for (bp = first_symbol; bp; bp = bp->next) {
2
Loop condition is false. Execution continues on line 1640
1636 ++nsyms;
1637 if (bp->class == TERM1)
1638 ++ntokens;
1639 }
1640 start_symbol = ntokens;
1641 nvars = nsyms - ntokens;
1642
1643 symbol_name = reallocarray(NULL((void *)0), nsyms, sizeof(char *));
1644 if (symbol_name == NULL((void *)0))
3
Assuming 'symbol_name' is not equal to NULL
4
Taking false branch
1645 no_space();
1646 symbol_value = reallocarray(NULL((void *)0), nsyms, sizeof(short));
1647 if (symbol_value == NULL((void *)0))
5
Assuming 'symbol_value' is not equal to NULL
6
Taking false branch
1648 no_space();
1649 symbol_prec = reallocarray(NULL((void *)0), nsyms, sizeof(short));
1650 if (symbol_prec == NULL((void *)0))
7
Assuming 'symbol_prec' is not equal to NULL
8
Taking false branch
1651 no_space();
1652 symbol_assoc = malloc(nsyms);
1653 if (symbol_assoc == NULL((void *)0))
9
Assuming 'symbol_assoc' is not equal to NULL
10
Taking false branch
1654 no_space();
1655
1656 v = reallocarray(NULL((void *)0), nsyms, sizeof(bucket *));
1657 if (v == NULL((void *)0))
11
Assuming 'v' is not equal to NULL
12
Taking false branch
1658 no_space();
1659
1660 v[0] = 0;
1661 v[start_symbol] = 0;
13
Storing null pointer value
1662
1663 i = 1;
1664 j = start_symbol + 1;
1665 for (bp = first_symbol; bp; bp = bp->next) {
14
Loop condition is false. Execution continues on line 1671
1666 if (bp->class == TERM1)
1667 v[i++] = bp;
1668 else
1669 v[j++] = bp;
1670 }
1671 assert(i == ntokens && j == nsyms)((i == ntokens && j == nsyms) ? (void)0 : __assert2("/usr/src/usr.bin/yacc/reader.c"
, 1671, __func__, "i == ntokens && j == nsyms"))
;
15
'?' condition is true
1672
1673 for (i = 1; i < ntokens; ++i)
16
Loop condition is false. Execution continues on line 1676
1674 v[i]->index = i;
1675
1676 goal->index = start_symbol + 1;
1677 k = start_symbol + 2;
1678 while (++i < nsyms)
17
Loop condition is false. Execution continues on line 1683
1679 if (v[i] != goal) {
1680 v[i]->index = k;
1681 ++k;
1682 }
1683 goal->value = 0;
1684 k = 1;
1685 for (i = start_symbol + 1; i < nsyms; ++i) {
18
Loop condition is false. Execution continues on line 1692
1686 if (v[i] != goal) {
1687 v[i]->value = k;
1688 ++k;
1689 }
1690 }
1691
1692 k = 0;
1693 for (i = 1; i < ntokens; ++i) {
19
Loop condition is false. Execution continues on line 1702
1694 n = v[i]->value;
1695 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 if (v[1]->value == UNDEFINED(-1))
20
Access to field 'value' results in a dereference of a null pointer
1703 v[1]->value = 256;
1704
1705 j = 0;
1706 n = 257;
1707 for (i = 2; i < ntokens; ++i) {
1708 if (v[i]->value == UNDEFINED(-1)) {
1709 while (j < k && n == symbol_value[j]) {
1710 while (++j < k && n == symbol_value[j])
1711 continue;
1712 ++n;
1713 }
1714 v[i]->value = n;
1715 ++n;
1716 }
1717 }
1718
1719 symbol_name[0] = name_pool + 8;
1720 symbol_value[0] = 0;
1721 symbol_prec[0] = 0;
1722 symbol_assoc[0] = TOKEN0;
1723 for (i = 1; i < ntokens; ++i) {
1724 symbol_name[i] = v[i]->name;
1725 symbol_value[i] = v[i]->value;
1726 symbol_prec[i] = v[i]->prec;
1727 symbol_assoc[i] = v[i]->assoc;
1728 }
1729 symbol_name[start_symbol] = name_pool;
1730 symbol_value[start_symbol] = -1;
1731 symbol_prec[start_symbol] = 0;
1732 symbol_assoc[start_symbol] = TOKEN0;
1733 for (++i; i < nsyms; ++i) {
1734 k = v[i]->index;
1735 symbol_name[k] = v[i]->name;
1736 symbol_value[k] = v[i]->value;
1737 symbol_prec[k] = v[i]->prec;
1738 symbol_assoc[k] = v[i]->assoc;
1739 }
1740
1741 free(v);
1742}
1743
1744
1745void
1746pack_grammar(void)
1747{
1748 int i, j;
1749 int assoc, pprec;
1750
1751 ritem = reallocarray(NULL((void *)0), nitems, sizeof(short));
1752 if (ritem == NULL((void *)0))
1753 no_space();
1754 rlhs = reallocarray(NULL((void *)0), nrules, sizeof(short));
1755 if (rlhs == NULL((void *)0))
1756 no_space();
1757 rrhs = reallocarray(NULL((void *)0), nrules + 1, sizeof(short));
1758 if (rrhs == NULL((void *)0))
1759 no_space();
1760 rprec = reallocarray(rprec, nrules, sizeof(short));
1761 if (rprec == NULL((void *)0))
1762 no_space();
1763 rassoc = realloc(rassoc, nrules);
1764 if (rassoc == NULL((void *)0))
1765 no_space();
1766
1767 ritem[0] = -1;
1768 ritem[1] = goal->index;
1769 ritem[2] = 0;
1770 ritem[3] = -2;
1771 rlhs[0] = 0;
1772 rlhs[1] = 0;
1773 rlhs[2] = start_symbol;
1774 rrhs[0] = 0;
1775 rrhs[1] = 0;
1776 rrhs[2] = 1;
1777
1778 j = 4;
1779 for (i = 3; i < nrules; ++i) {
1780 rlhs[i] = plhs[i]->index;
1781 rrhs[i] = j;
1782 assoc = TOKEN0;
1783 pprec = 0;
1784 while (pitem[j]) {
1785 ritem[j] = pitem[j]->index;
1786 if (pitem[j]->class == TERM1) {
1787 pprec = pitem[j]->prec;
1788 assoc = pitem[j]->assoc;
1789 }
1790 ++j;
1791 }
1792 ritem[j] = -i;
1793 ++j;
1794 if (rprec[i] == UNDEFINED(-1)) {
1795 rprec[i] = pprec;
1796 rassoc[i] = assoc;
1797 }
1798 }
1799 rrhs[i] = j;
1800
1801 free(plhs);
1802 free(pitem);
1803}
1804
1805
1806void
1807print_grammar(void)
1808{
1809 int i, j, k;
1810 int spacing = 0;
1811 FILE *f = verbose_file;
1812
1813 if (!vflag)
1814 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)(!__isthreaded ? __sputc(' ', f) : (putc)(' ', f));
1828 putc('|', f)(!__isthreaded ? __sputc('|', f) : (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)(!__isthreaded ? __sputc('\n', f) : (putc)('\n', f));
1837 }
1838}
1839
1840
1841void
1842reader(void)
1843{
1844 write_section(banner);
1845 create_symbol_table();
1846 read_declarations();
1847 read_grammar();
1848 free_symbol_table();
1849 free_tags();
1850 pack_names();
1851 check_symbols();
1852 pack_symbols();
1
Calling 'pack_symbols'
1853 pack_grammar();
1854 free_symbols();
1855 print_grammar();
1856}