Annotation of src/usr.bin/yacc/reader.c, Revision 1.22
1.22 ! nicm 1: /* $OpenBSD: reader.c,v 1.21 2009/10/27 23:59:50 deraadt Exp $ */
1.5 deraadt 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.
1.14 millert 19: * 3. Neither the name of the University nor the names of its contributors
1.5 deraadt 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: */
1.1 deraadt 35:
36: #include "defs.h"
37:
38: /* The line size must be a positive integer. One hundred was chosen */
39: /* because few lines in Yacc input grammars exceed 100 characters. */
40: /* Note that if a line exceeds LINESIZE characters, the line buffer */
1.11 todd 41: /* will be expanded to accommodate it. */
1.1 deraadt 42:
43: #define LINESIZE 100
44:
45: char *cache;
46: int cinc, cache_size;
47:
48: int ntags, tagmax;
49: char **tag_table;
50:
51: char saw_eof, unionized;
52: char *cptr, *line;
53: int linesize;
54:
55: bucket *goal;
56: int prec;
57: int gensym;
58: char last_was_action;
59:
60: int maxitems;
61: bucket **pitem;
62:
63: int maxrules;
64: bucket **plhs;
65:
66: int name_pool_size;
67: char *name_pool;
68:
1.10 millert 69: void cachec(int);
70: void get_line(void);
71: char * dup_line(void);
72: void skip_comment(void);
73: int nextc(void);
74: int keyword(void);
75: void copy_ident(void);
76: void copy_text(void);
77: void copy_union(void);
1.17 deraadt 78: int hexval(int);
1.10 millert 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);
1.8 pvalchev 106:
1.1 deraadt 107: char line_format[] = "#line %d \"%s\"\n";
108:
1.7 deraadt 109: void
1.15 pvalchev 110: cachec(int c)
1.1 deraadt 111: {
112: assert(cinc >= 0);
113: if (cinc >= cache_size)
114: {
115: cache_size += 256;
116: cache = REALLOC(cache, cache_size);
117: if (cache == 0) no_space();
118: }
119: cache[cinc] = c;
120: ++cinc;
121: }
122:
123:
1.7 deraadt 124: void
1.15 pvalchev 125: get_line(void)
1.1 deraadt 126: {
1.9 mpech 127: FILE *f = input_file;
128: int c;
129: int i;
1.1 deraadt 130:
131: if (saw_eof || (c = getc(f)) == EOF)
132: {
133: if (line) { FREE(line); line = 0; }
134: cptr = 0;
135: saw_eof = 1;
136: return;
137: }
138:
139: if (line == 0 || linesize != (LINESIZE + 1))
140: {
141: if (line) FREE(line);
142: linesize = LINESIZE + 1;
143: line = MALLOC(linesize);
144: if (line == 0) no_space();
145: }
146:
147: i = 0;
148: ++lineno;
149: for (;;)
150: {
151: line[i] = c;
152: if (c == '\n') { cptr = line; return; }
153: if (++i >= linesize)
154: {
155: linesize += LINESIZE;
156: line = REALLOC(line, linesize);
157: if (line == 0) no_space();
158: }
159: c = getc(f);
160: if (c == EOF)
161: {
162: line[i] = '\n';
163: saw_eof = 1;
164: cptr = line;
165: return;
166: }
167: }
168: }
169:
170:
171: char *
1.15 pvalchev 172: dup_line(void)
1.1 deraadt 173: {
1.9 mpech 174: char *p, *s, *t;
1.1 deraadt 175:
176: if (line == 0) return (0);
177: s = line;
178: while (*s != '\n') ++s;
179: p = MALLOC(s - line + 1);
180: if (p == 0) no_space();
181:
182: s = line;
183: t = p;
184: while ((*t++ = *s++) != '\n') continue;
185: return (p);
186: }
187:
188:
1.7 deraadt 189: void
1.15 pvalchev 190: skip_comment(void)
1.1 deraadt 191: {
1.9 mpech 192: char *s;
1.1 deraadt 193:
194: int st_lineno = lineno;
195: char *st_line = dup_line();
196: char *st_cptr = st_line + (cptr - line);
197:
198: s = cptr + 2;
199: for (;;)
200: {
201: if (*s == '*' && s[1] == '/')
202: {
203: cptr = s + 2;
204: FREE(st_line);
205: return;
206: }
207: if (*s == '\n')
208: {
209: get_line();
210: if (line == 0)
211: unterminated_comment(st_lineno, st_line, st_cptr);
212: s = cptr;
213: }
214: else
215: ++s;
216: }
217: }
218:
219:
220: int
1.15 pvalchev 221: nextc(void)
1.1 deraadt 222: {
1.9 mpech 223: char *s;
1.1 deraadt 224:
225: if (line == 0)
226: {
227: get_line();
228: if (line == 0)
229: return (EOF);
230: }
231:
232: s = cptr;
233: for (;;)
234: {
235: switch (*s)
236: {
237: case '\n':
238: get_line();
239: if (line == 0) return (EOF);
240: s = cptr;
241: break;
242:
243: case ' ':
244: case '\t':
245: case '\f':
246: case '\r':
247: case '\v':
248: case ',':
249: case ';':
250: ++s;
251: break;
252:
253: case '\\':
254: cptr = s;
255: return ('%');
256:
257: case '/':
258: if (s[1] == '*')
259: {
260: cptr = s;
261: skip_comment();
262: s = cptr;
263: break;
264: }
265: else if (s[1] == '/')
266: {
267: get_line();
268: if (line == 0) return (EOF);
269: s = cptr;
270: break;
271: }
272: /* fall through */
273:
274: default:
275: cptr = s;
276: return (*s);
277: }
278: }
279: }
280:
281:
282: int
1.15 pvalchev 283: keyword(void)
1.1 deraadt 284: {
1.9 mpech 285: int c;
1.1 deraadt 286: char *t_cptr = cptr;
287:
288: c = *++cptr;
289: if (isalpha(c))
290: {
291: cinc = 0;
292: for (;;)
293: {
294: if (isalpha(c))
295: {
296: if (isupper(c)) c = tolower(c);
297: cachec(c);
298: }
299: else if (isdigit(c) || c == '_' || c == '.' || c == '$')
300: cachec(c);
301: else
302: break;
303: c = *++cptr;
304: }
305: cachec(NUL);
306:
307: if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0)
308: return (TOKEN);
309: if (strcmp(cache, "type") == 0)
310: return (TYPE);
311: if (strcmp(cache, "left") == 0)
312: return (LEFT);
313: if (strcmp(cache, "right") == 0)
314: return (RIGHT);
315: if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0)
316: return (NONASSOC);
317: if (strcmp(cache, "start") == 0)
318: return (START);
319: if (strcmp(cache, "union") == 0)
320: return (UNION);
321: if (strcmp(cache, "ident") == 0)
322: return (IDENT);
1.2 etheisen 323: if (strcmp(cache, "expect") == 0)
324: return (EXPECT);
1.1 deraadt 325: }
326: else
327: {
328: ++cptr;
329: if (c == '{')
330: return (TEXT);
331: if (c == '%' || c == '\\')
332: return (MARK);
333: if (c == '<')
334: return (LEFT);
335: if (c == '>')
336: return (RIGHT);
337: if (c == '0')
338: return (TOKEN);
339: if (c == '2')
340: return (NONASSOC);
341: }
342: syntax_error(lineno, line, t_cptr);
343: /*NOTREACHED*/
1.8 pvalchev 344: return (0);
1.1 deraadt 345: }
346:
347:
1.7 deraadt 348: void
1.15 pvalchev 349: copy_ident(void)
1.1 deraadt 350: {
1.9 mpech 351: int c;
352: FILE *f = output_file;
1.1 deraadt 353:
354: c = nextc();
355: if (c == EOF) unexpected_EOF();
356: if (c != '"') syntax_error(lineno, line, cptr);
357: ++outline;
358: fprintf(f, "#ident \"");
359: for (;;)
360: {
361: c = *++cptr;
362: if (c == '\n')
363: {
364: fprintf(f, "\"\n");
365: return;
366: }
367: putc(c, f);
368: if (c == '"')
369: {
370: putc('\n', f);
371: ++cptr;
372: return;
373: }
374: }
375: }
376:
377:
1.8 pvalchev 378: void
1.15 pvalchev 379: copy_text(void)
1.1 deraadt 380: {
1.9 mpech 381: int c;
1.1 deraadt 382: int quote;
1.9 mpech 383: FILE *f = text_file;
1.1 deraadt 384: int need_newline = 0;
385: int t_lineno = lineno;
386: char *t_line = dup_line();
387: char *t_cptr = t_line + (cptr - line - 2);
388:
389: if (*cptr == '\n')
390: {
391: get_line();
392: if (line == 0)
393: unterminated_text(t_lineno, t_line, t_cptr);
394: }
395: if (!lflag) fprintf(f, line_format, lineno, input_file_name);
396:
397: loop:
398: c = *cptr++;
399: switch (c)
400: {
401: case '\n':
402: next_line:
403: putc('\n', f);
404: need_newline = 0;
405: get_line();
406: if (line) goto loop;
407: unterminated_text(t_lineno, t_line, t_cptr);
408:
409: case '\'':
410: case '"':
411: {
412: int s_lineno = lineno;
413: char *s_line = dup_line();
414: char *s_cptr = s_line + (cptr - line - 1);
415:
416: quote = c;
417: putc(c, f);
418: for (;;)
419: {
420: c = *cptr++;
421: putc(c, f);
422: if (c == quote)
423: {
424: need_newline = 1;
425: FREE(s_line);
426: goto loop;
427: }
428: if (c == '\n')
429: unterminated_string(s_lineno, s_line, s_cptr);
430: if (c == '\\')
431: {
432: c = *cptr++;
433: putc(c, f);
434: if (c == '\n')
435: {
436: get_line();
437: if (line == 0)
438: unterminated_string(s_lineno, s_line, s_cptr);
439: }
440: }
441: }
442: }
443:
444: case '/':
445: putc(c, f);
446: need_newline = 1;
447: c = *cptr;
448: if (c == '/')
449: {
450: putc('*', f);
451: while ((c = *++cptr) != '\n')
452: {
453: if (c == '*' && cptr[1] == '/')
454: fprintf(f, "* ");
455: else
456: putc(c, f);
457: }
458: fprintf(f, "*/");
459: goto next_line;
460: }
461: if (c == '*')
462: {
463: int c_lineno = lineno;
464: char *c_line = dup_line();
465: char *c_cptr = c_line + (cptr - line - 1);
466:
467: putc('*', f);
468: ++cptr;
469: for (;;)
470: {
471: c = *cptr++;
472: putc(c, f);
473: if (c == '*' && *cptr == '/')
474: {
475: putc('/', f);
476: ++cptr;
477: FREE(c_line);
478: goto loop;
479: }
480: if (c == '\n')
481: {
482: get_line();
483: if (line == 0)
484: unterminated_comment(c_lineno, c_line, c_cptr);
485: }
486: }
487: }
488: need_newline = 1;
489: goto loop;
490:
491: case '%':
492: case '\\':
493: if (*cptr == '}')
494: {
495: if (need_newline) putc('\n', f);
496: ++cptr;
497: FREE(t_line);
498: return;
499: }
500: /* fall through */
501:
502: default:
503: putc(c, f);
504: need_newline = 1;
505: goto loop;
506: }
507: }
508:
509:
1.8 pvalchev 510: void
1.15 pvalchev 511: copy_union(void)
1.1 deraadt 512: {
1.9 mpech 513: int c;
1.1 deraadt 514: int quote;
515: int depth;
516: int u_lineno = lineno;
517: char *u_line = dup_line();
518: char *u_cptr = u_line + (cptr - line - 6);
519:
520: if (unionized) over_unionized(cptr - 6);
521: unionized = 1;
522:
523: if (!lflag)
524: fprintf(text_file, line_format, lineno, input_file_name);
525:
1.16 deraadt 526: fprintf(text_file, "#ifndef YYSTYPE_DEFINED\n");
527: fprintf(text_file, "#define YYSTYPE_DEFINED\n");
1.1 deraadt 528: fprintf(text_file, "typedef union");
1.16 deraadt 529: if (dflag) fprintf(union_file, "#ifndef YYSTYPE_DEFINED\n");
530: if (dflag) fprintf(union_file, "#define YYSTYPE_DEFINED\n");
1.1 deraadt 531: if (dflag) fprintf(union_file, "typedef union");
532:
533: depth = 0;
534: loop:
535: c = *cptr++;
536: putc(c, text_file);
537: if (dflag) putc(c, union_file);
538: switch (c)
539: {
540: case '\n':
541: next_line:
542: get_line();
543: if (line == 0) unterminated_union(u_lineno, u_line, u_cptr);
544: goto loop;
545:
546: case '{':
547: ++depth;
548: goto loop;
549:
550: case '}':
551: if (--depth == 0)
552: {
553: fprintf(text_file, " YYSTYPE;\n");
1.16 deraadt 554: fprintf(text_file, "#endif /* YYSTYPE_DEFINED */\n");
1.1 deraadt 555: FREE(u_line);
556: return;
557: }
558: goto loop;
559:
560: case '\'':
561: case '"':
562: {
563: int s_lineno = lineno;
564: char *s_line = dup_line();
565: char *s_cptr = s_line + (cptr - line - 1);
566:
567: quote = c;
568: for (;;)
569: {
570: c = *cptr++;
571: putc(c, text_file);
572: if (dflag) putc(c, union_file);
573: if (c == quote)
574: {
575: FREE(s_line);
576: goto loop;
577: }
578: if (c == '\n')
579: unterminated_string(s_lineno, s_line, s_cptr);
580: if (c == '\\')
581: {
582: c = *cptr++;
583: putc(c, text_file);
584: if (dflag) putc(c, union_file);
585: if (c == '\n')
586: {
587: get_line();
588: if (line == 0)
589: unterminated_string(s_lineno, s_line, s_cptr);
590: }
591: }
592: }
593: }
594:
595: case '/':
596: c = *cptr;
597: if (c == '/')
598: {
599: putc('*', text_file);
600: if (dflag) putc('*', union_file);
601: while ((c = *++cptr) != '\n')
602: {
603: if (c == '*' && cptr[1] == '/')
604: {
605: fprintf(text_file, "* ");
606: if (dflag) fprintf(union_file, "* ");
607: }
608: else
609: {
610: putc(c, text_file);
611: if (dflag) putc(c, union_file);
612: }
613: }
614: fprintf(text_file, "*/\n");
615: if (dflag) fprintf(union_file, "*/\n");
616: goto next_line;
617: }
618: if (c == '*')
619: {
620: int c_lineno = lineno;
621: char *c_line = dup_line();
622: char *c_cptr = c_line + (cptr - line - 1);
623:
624: putc('*', text_file);
625: if (dflag) putc('*', union_file);
626: ++cptr;
627: for (;;)
628: {
629: c = *cptr++;
630: putc(c, text_file);
631: if (dflag) putc(c, union_file);
632: if (c == '*' && *cptr == '/')
633: {
634: putc('/', text_file);
635: if (dflag) putc('/', union_file);
636: ++cptr;
637: FREE(c_line);
638: goto loop;
639: }
640: if (c == '\n')
641: {
642: get_line();
643: if (line == 0)
644: unterminated_comment(c_lineno, c_line, c_cptr);
645: }
646: }
647: }
648: goto loop;
649:
650: default:
651: goto loop;
652: }
653: }
654:
655:
656: int
1.15 pvalchev 657: hexval(int c)
1.1 deraadt 658: {
659: if (c >= '0' && c <= '9')
660: return (c - '0');
661: if (c >= 'A' && c <= 'F')
662: return (c - 'A' + 10);
663: if (c >= 'a' && c <= 'f')
664: return (c - 'a' + 10);
665: return (-1);
666: }
667:
668:
669: bucket *
1.15 pvalchev 670: get_literal(void)
1.1 deraadt 671: {
1.9 mpech 672: int c, quote;
673: int i;
674: int n;
675: char *s;
676: bucket *bp;
1.1 deraadt 677: int s_lineno = lineno;
678: char *s_line = dup_line();
679: char *s_cptr = s_line + (cptr - line);
680:
681: quote = *cptr++;
682: cinc = 0;
683: for (;;)
684: {
685: c = *cptr++;
686: if (c == quote) break;
687: if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr);
688: if (c == '\\')
689: {
690: char *c_cptr = cptr - 1;
691:
692: c = *cptr++;
693: switch (c)
694: {
695: case '\n':
696: get_line();
697: if (line == 0) unterminated_string(s_lineno, s_line, s_cptr);
698: continue;
699:
700: case '0': case '1': case '2': case '3':
701: case '4': case '5': case '6': case '7':
702: n = c - '0';
703: c = *cptr;
704: if (IS_OCTAL(c))
705: {
706: n = (n << 3) + (c - '0');
707: c = *++cptr;
708: if (IS_OCTAL(c))
709: {
710: n = (n << 3) + (c - '0');
711: ++cptr;
712: }
713: }
714: if (n > MAXCHAR) illegal_character(c_cptr);
715: c = n;
716: break;
717:
718: case 'x':
719: c = *cptr++;
720: n = hexval(c);
721: if (n < 0 || n >= 16)
722: illegal_character(c_cptr);
723: for (;;)
724: {
725: c = *cptr;
726: i = hexval(c);
727: if (i < 0 || i >= 16) break;
728: ++cptr;
729: n = (n << 4) + i;
730: if (n > MAXCHAR) illegal_character(c_cptr);
731: }
732: c = n;
733: break;
734:
735: case 'a': c = 7; break;
736: case 'b': c = '\b'; break;
737: case 'f': c = '\f'; break;
738: case 'n': c = '\n'; break;
739: case 'r': c = '\r'; break;
740: case 't': c = '\t'; break;
741: case 'v': c = '\v'; break;
742: }
743: }
744: cachec(c);
745: }
746: FREE(s_line);
747:
748: n = cinc;
749: s = MALLOC(n);
750: if (s == 0) no_space();
1.17 deraadt 751:
1.1 deraadt 752: for (i = 0; i < n; ++i)
753: s[i] = cache[i];
754:
755: cinc = 0;
756: if (n == 1)
757: cachec('\'');
758: else
759: cachec('"');
760:
761: for (i = 0; i < n; ++i)
762: {
763: c = ((unsigned char *)s)[i];
764: if (c == '\\' || c == cache[0])
765: {
766: cachec('\\');
767: cachec(c);
768: }
769: else if (isprint(c))
770: cachec(c);
771: else
772: {
773: cachec('\\');
774: switch (c)
775: {
776: case 7: cachec('a'); break;
777: case '\b': cachec('b'); break;
778: case '\f': cachec('f'); break;
779: case '\n': cachec('n'); break;
780: case '\r': cachec('r'); break;
781: case '\t': cachec('t'); break;
782: case '\v': cachec('v'); break;
783: default:
784: cachec(((c >> 6) & 7) + '0');
785: cachec(((c >> 3) & 7) + '0');
786: cachec((c & 7) + '0');
787: break;
788: }
789: }
790: }
791:
792: if (n == 1)
793: cachec('\'');
794: else
795: cachec('"');
796:
797: cachec(NUL);
798: bp = lookup(cache);
799: bp->class = TERM;
800: if (n == 1 && bp->value == UNDEFINED)
801: bp->value = *(unsigned char *)s;
802: FREE(s);
803:
804: return (bp);
805: }
806:
807:
808: int
1.15 pvalchev 809: is_reserved(char *name)
1.1 deraadt 810: {
811: char *s;
812:
813: if (strcmp(name, ".") == 0 ||
814: strcmp(name, "$accept") == 0 ||
815: strcmp(name, "$end") == 0)
816: return (1);
817:
818: if (name[0] == '$' && name[1] == '$' && isdigit(name[2]))
819: {
820: s = name + 3;
821: while (isdigit(*s)) ++s;
822: if (*s == NUL) return (1);
823: }
824:
825: return (0);
826: }
827:
828:
829: bucket *
1.15 pvalchev 830: get_name(void)
1.1 deraadt 831: {
1.9 mpech 832: int c;
1.1 deraadt 833:
834: cinc = 0;
835: for (c = *cptr; IS_IDENT(c); c = *++cptr)
836: cachec(c);
837: cachec(NUL);
838:
839: if (is_reserved(cache)) used_reserved(cache);
840:
841: return (lookup(cache));
842: }
843:
844:
845: int
1.15 pvalchev 846: get_number(void)
1.1 deraadt 847: {
1.9 mpech 848: int c;
849: int n;
1.1 deraadt 850:
851: n = 0;
852: for (c = *cptr; isdigit(c); c = *++cptr)
853: n = 10*n + (c - '0');
854:
855: return (n);
856: }
857:
858:
859: char *
1.15 pvalchev 860: get_tag(void)
1.1 deraadt 861: {
1.9 mpech 862: int c;
863: int i;
864: char *s;
1.1 deraadt 865: int t_lineno = lineno;
866: char *t_line = dup_line();
867: char *t_cptr = t_line + (cptr - line);
868:
869: ++cptr;
870: c = nextc();
871: if (c == EOF) unexpected_EOF();
872: if (!isalpha(c) && c != '_' && c != '$')
873: illegal_tag(t_lineno, t_line, t_cptr);
874:
875: cinc = 0;
876: do { cachec(c); c = *++cptr; } while (IS_IDENT(c));
877: cachec(NUL);
878:
879: c = nextc();
880: if (c == EOF) unexpected_EOF();
881: if (c != '>')
882: illegal_tag(t_lineno, t_line, t_cptr);
1.6 deraadt 883: FREE(t_line);
1.1 deraadt 884: ++cptr;
885:
886: for (i = 0; i < ntags; ++i)
887: {
888: if (strcmp(cache, tag_table[i]) == 0)
889: return (tag_table[i]);
890: }
891:
892: if (ntags >= tagmax)
893: {
894: tagmax += 16;
895: tag_table = (char **)
896: (tag_table ? REALLOC(tag_table, tagmax*sizeof(char *))
897: : MALLOC(tagmax*sizeof(char *)));
898: if (tag_table == 0) no_space();
899: }
900:
901: s = MALLOC(cinc);
902: if (s == 0) no_space();
1.13 deraadt 903: strlcpy(s, cache, cinc);
1.1 deraadt 904: tag_table[ntags] = s;
905: ++ntags;
906: return (s);
907: }
908:
909:
1.8 pvalchev 910: void
1.15 pvalchev 911: declare_tokens(int assoc)
1.1 deraadt 912: {
1.9 mpech 913: int c;
914: bucket *bp;
1.1 deraadt 915: int value;
916: char *tag = 0;
917:
918: if (assoc != TOKEN) ++prec;
919:
920: c = nextc();
921: if (c == EOF) unexpected_EOF();
922: if (c == '<')
923: {
924: tag = get_tag();
925: c = nextc();
926: if (c == EOF) unexpected_EOF();
927: }
928:
929: for (;;)
930: {
931: if (isalpha(c) || c == '_' || c == '.' || c == '$')
932: bp = get_name();
933: else if (c == '\'' || c == '"')
934: bp = get_literal();
935: else
936: return;
937:
938: if (bp == goal) tokenized_start(bp->name);
939: bp->class = TERM;
940:
941: if (tag)
942: {
943: if (bp->tag && tag != bp->tag)
944: retyped_warning(bp->name);
945: bp->tag = tag;
946: }
947:
948: if (assoc != TOKEN)
949: {
950: if (bp->prec && prec != bp->prec)
951: reprec_warning(bp->name);
952: bp->assoc = assoc;
953: bp->prec = prec;
954: }
955:
956: c = nextc();
957: if (c == EOF) unexpected_EOF();
958: value = UNDEFINED;
959: if (isdigit(c))
960: {
961: value = get_number();
962: if (bp->value != UNDEFINED && value != bp->value)
963: revalued_warning(bp->name);
964: bp->value = value;
965: c = nextc();
966: if (c == EOF) unexpected_EOF();
967: }
968: }
969: }
970:
971:
1.4 etheisen 972: /*
973: * %expect requires special handling
974: * as it really isn't part of the yacc
975: * grammar only a flag for yacc proper.
976: */
1.8 pvalchev 977: void
1.15 pvalchev 978: declare_expect(int assoc)
1.4 etheisen 979: {
1.9 mpech 980: int c;
1.4 etheisen 981:
982: if (assoc != EXPECT) ++prec;
983:
984: /*
985: * Stay away from nextc - doesn't
986: * detect EOL and will read to EOF.
987: */
988: c = *++cptr;
989: if (c == EOF) unexpected_EOF();
990:
991: for(;;)
992: {
993: if (isdigit(c))
994: {
995: SRexpect = get_number();
996: break;
997: }
998: /*
999: * Looking for number before EOL.
1000: * Spaces, tabs, and numbers are ok,
1001: * words, punc., etc. are syntax errors.
1002: */
1003: else if (c == '\n' || isalpha(c) || !isspace(c))
1004: {
1005: syntax_error(lineno, line, cptr);
1006: }
1007: else
1008: {
1009: c = *++cptr;
1010: if (c == EOF) unexpected_EOF();
1011: }
1012: }
1013: }
1014:
1015:
1.8 pvalchev 1016: void
1.15 pvalchev 1017: declare_types(void)
1.1 deraadt 1018: {
1.9 mpech 1019: int c;
1020: bucket *bp;
1.1 deraadt 1021: char *tag;
1022:
1023: c = nextc();
1024: if (c == EOF) unexpected_EOF();
1025: if (c != '<') syntax_error(lineno, line, cptr);
1026: tag = get_tag();
1027:
1028: for (;;)
1029: {
1030: c = nextc();
1031: if (isalpha(c) || c == '_' || c == '.' || c == '$')
1032: bp = get_name();
1033: else if (c == '\'' || c == '"')
1034: bp = get_literal();
1035: else
1036: return;
1037:
1038: if (bp->tag && tag != bp->tag)
1039: retyped_warning(bp->name);
1040: bp->tag = tag;
1041: }
1042: }
1043:
1044:
1.8 pvalchev 1045: void
1.15 pvalchev 1046: declare_start(void)
1.1 deraadt 1047: {
1.9 mpech 1048: int c;
1049: bucket *bp;
1.1 deraadt 1050:
1051: c = nextc();
1052: if (c == EOF) unexpected_EOF();
1053: if (!isalpha(c) && c != '_' && c != '.' && c != '$')
1054: syntax_error(lineno, line, cptr);
1055: bp = get_name();
1056: if (bp->class == TERM)
1057: terminal_start(bp->name);
1058: if (goal && goal != bp)
1059: restarted_warning();
1060: goal = bp;
1061: }
1062:
1063:
1.8 pvalchev 1064: void
1.15 pvalchev 1065: read_declarations(void)
1.1 deraadt 1066: {
1.9 mpech 1067: int c, k;
1.1 deraadt 1068:
1069: cache_size = 256;
1070: cache = MALLOC(cache_size);
1071: if (cache == 0) no_space();
1072:
1073: for (;;)
1074: {
1075: c = nextc();
1076: if (c == EOF) unexpected_EOF();
1077: if (c != '%') syntax_error(lineno, line, cptr);
1078: switch (k = keyword())
1079: {
1080: case MARK:
1081: return;
1082:
1083: case IDENT:
1084: copy_ident();
1085: break;
1086:
1087: case TEXT:
1088: copy_text();
1089: break;
1090:
1091: case UNION:
1092: copy_union();
1093: break;
1094:
1095: case TOKEN:
1096: case LEFT:
1097: case RIGHT:
1098: case NONASSOC:
1099: declare_tokens(k);
1100: break;
1.2 etheisen 1101:
1.4 etheisen 1102: case EXPECT:
1103: declare_expect(k);
1104: break;
1105:
1.1 deraadt 1106: case TYPE:
1107: declare_types();
1108: break;
1109:
1110: case START:
1111: declare_start();
1112: break;
1113: }
1114: }
1115: }
1116:
1117:
1.8 pvalchev 1118: void
1.15 pvalchev 1119: initialize_grammar(void)
1.1 deraadt 1120: {
1121: nitems = 4;
1122: maxitems = 300;
1.22 ! nicm 1123: pitem = (bucket **) CALLOC(maxitems, sizeof(bucket *));
1.1 deraadt 1124: if (pitem == 0) no_space();
1125:
1126: nrules = 3;
1127: maxrules = 100;
1128: plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *));
1129: if (plhs == 0) no_space();
1130: plhs[0] = 0;
1131: plhs[1] = 0;
1132: plhs[2] = 0;
1133: rprec = (short *) MALLOC(maxrules*sizeof(short));
1134: if (rprec == 0) no_space();
1135: rprec[0] = 0;
1136: rprec[1] = 0;
1137: rprec[2] = 0;
1138: rassoc = (char *) MALLOC(maxrules*sizeof(char));
1139: if (rassoc == 0) no_space();
1140: rassoc[0] = TOKEN;
1141: rassoc[1] = TOKEN;
1142: rassoc[2] = TOKEN;
1143: }
1144:
1145:
1.8 pvalchev 1146: void
1.15 pvalchev 1147: expand_items(void)
1.1 deraadt 1148: {
1.22 ! nicm 1149: int olditems = maxitems;
1.1 deraadt 1150: maxitems += 300;
1151: pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *));
1152: if (pitem == 0) no_space();
1.22 ! nicm 1153: memset(pitem + olditems, 0, (maxitems - olditems)*sizeof(bucket *));
1.1 deraadt 1154: }
1155:
1156:
1.8 pvalchev 1157: void
1.15 pvalchev 1158: expand_rules(void)
1.1 deraadt 1159: {
1160: maxrules += 100;
1161: plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *));
1162: if (plhs == 0) no_space();
1163: rprec = (short *) REALLOC(rprec, maxrules*sizeof(short));
1164: if (rprec == 0) no_space();
1165: rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char));
1166: if (rassoc == 0) no_space();
1167: }
1168:
1169:
1.8 pvalchev 1170: void
1.15 pvalchev 1171: advance_to_start(void)
1.1 deraadt 1172: {
1.9 mpech 1173: int c;
1174: bucket *bp;
1.1 deraadt 1175: char *s_cptr;
1176: int s_lineno;
1177:
1178: for (;;)
1179: {
1180: c = nextc();
1181: if (c != '%') break;
1182: s_cptr = cptr;
1183: switch (keyword())
1184: {
1185: case MARK:
1186: no_grammar();
1187:
1188: case TEXT:
1189: copy_text();
1190: break;
1191:
1192: case START:
1193: declare_start();
1194: break;
1195:
1196: default:
1197: syntax_error(lineno, line, s_cptr);
1198: }
1199: }
1200:
1201: c = nextc();
1202: if (!isalpha(c) && c != '_' && c != '.' && c != '_')
1203: syntax_error(lineno, line, cptr);
1204: bp = get_name();
1205: if (goal == 0)
1206: {
1207: if (bp->class == TERM)
1208: terminal_start(bp->name);
1209: goal = bp;
1210: }
1211:
1212: s_lineno = lineno;
1213: c = nextc();
1214: if (c == EOF) unexpected_EOF();
1215: if (c != ':') syntax_error(lineno, line, cptr);
1216: start_rule(bp, s_lineno);
1217: ++cptr;
1218: }
1219:
1220:
1.8 pvalchev 1221: void
1.15 pvalchev 1222: start_rule(bucket *bp, int s_lineno)
1.1 deraadt 1223: {
1224: if (bp->class == TERM)
1225: terminal_lhs(s_lineno);
1226: bp->class = NONTERM;
1227: if (nrules >= maxrules)
1228: expand_rules();
1229: plhs[nrules] = bp;
1230: rprec[nrules] = UNDEFINED;
1231: rassoc[nrules] = TOKEN;
1232: }
1233:
1234:
1.8 pvalchev 1235: void
1.15 pvalchev 1236: end_rule(void)
1.1 deraadt 1237: {
1.9 mpech 1238: int i;
1.1 deraadt 1239:
1240: if (!last_was_action && plhs[nrules]->tag)
1241: {
1242: for (i = nitems - 1; pitem[i]; --i) continue;
1.22 ! nicm 1243: if (i == maxitems - 1 || pitem[i+1] == 0 ||
! 1244: pitem[i+1]->tag != plhs[nrules]->tag)
1.1 deraadt 1245: default_action_warning();
1246: }
1247:
1248: last_was_action = 0;
1249: if (nitems >= maxitems) expand_items();
1250: pitem[nitems] = 0;
1251: ++nitems;
1252: ++nrules;
1253: }
1254:
1255:
1.8 pvalchev 1256: void
1.15 pvalchev 1257: insert_empty_rule(void)
1.1 deraadt 1258: {
1.9 mpech 1259: bucket *bp, **bpp;
1.1 deraadt 1260:
1261: assert(cache);
1.12 deraadt 1262: snprintf(cache, cache_size, "$$%d", ++gensym);
1.1 deraadt 1263: bp = make_bucket(cache);
1264: last_symbol->next = bp;
1265: last_symbol = bp;
1266: bp->tag = plhs[nrules]->tag;
1267: bp->class = NONTERM;
1268:
1269: if ((nitems += 2) > maxitems)
1270: expand_items();
1271: bpp = pitem + nitems - 1;
1272: *bpp-- = bp;
1.8 pvalchev 1273: while ((bpp[0] = bpp[-1])) --bpp;
1.1 deraadt 1274:
1275: if (++nrules >= maxrules)
1276: expand_rules();
1277: plhs[nrules] = plhs[nrules-1];
1278: plhs[nrules-1] = bp;
1279: rprec[nrules] = rprec[nrules-1];
1280: rprec[nrules-1] = 0;
1281: rassoc[nrules] = rassoc[nrules-1];
1282: rassoc[nrules-1] = TOKEN;
1283: }
1284:
1285:
1.8 pvalchev 1286: void
1.15 pvalchev 1287: add_symbol(void)
1.1 deraadt 1288: {
1.9 mpech 1289: int c;
1290: bucket *bp;
1.1 deraadt 1291: int s_lineno = lineno;
1292:
1293: c = *cptr;
1294: if (c == '\'' || c == '"')
1295: bp = get_literal();
1296: else
1297: bp = get_name();
1298:
1299: c = nextc();
1300: if (c == ':')
1301: {
1302: end_rule();
1303: start_rule(bp, s_lineno);
1304: ++cptr;
1305: return;
1306: }
1307:
1308: if (last_was_action)
1309: insert_empty_rule();
1310: last_was_action = 0;
1311:
1312: if (++nitems > maxitems)
1313: expand_items();
1314: pitem[nitems-1] = bp;
1315: }
1316:
1317:
1.8 pvalchev 1318: void
1.15 pvalchev 1319: copy_action(void)
1.1 deraadt 1320: {
1.9 mpech 1321: int c;
1322: int i, n;
1.1 deraadt 1323: int depth;
1324: int quote;
1325: char *tag;
1.9 mpech 1326: FILE *f = action_file;
1.1 deraadt 1327: int a_lineno = lineno;
1328: char *a_line = dup_line();
1329: char *a_cptr = a_line + (cptr - line);
1330:
1331: if (last_was_action)
1332: insert_empty_rule();
1333: last_was_action = 1;
1334:
1335: fprintf(f, "case %d:\n", nrules - 2);
1336: if (!lflag)
1337: fprintf(f, line_format, lineno, input_file_name);
1338: if (*cptr == '=') ++cptr;
1339:
1340: n = 0;
1341: for (i = nitems - 1; pitem[i]; --i) ++n;
1342:
1343: depth = 0;
1344: loop:
1345: c = *cptr;
1346: if (c == '$')
1347: {
1348: if (cptr[1] == '<')
1349: {
1350: int d_lineno = lineno;
1351: char *d_line = dup_line();
1352: char *d_cptr = d_line + (cptr - line);
1353:
1354: ++cptr;
1355: tag = get_tag();
1356: c = *cptr;
1357: if (c == '$')
1358: {
1359: fprintf(f, "yyval.%s", tag);
1360: ++cptr;
1361: FREE(d_line);
1362: goto loop;
1363: }
1364: else if (isdigit(c))
1365: {
1366: i = get_number();
1367: if (i > n) dollar_warning(d_lineno, i);
1368: fprintf(f, "yyvsp[%d].%s", i - n, tag);
1369: FREE(d_line);
1370: goto loop;
1371: }
1372: else if (c == '-' && isdigit(cptr[1]))
1373: {
1374: ++cptr;
1375: i = -get_number() - n;
1376: fprintf(f, "yyvsp[%d].%s", i, tag);
1377: FREE(d_line);
1378: goto loop;
1379: }
1380: else
1381: dollar_error(d_lineno, d_line, d_cptr);
1382: }
1383: else if (cptr[1] == '$')
1384: {
1385: if (ntags)
1386: {
1387: tag = plhs[nrules]->tag;
1388: if (tag == 0) untyped_lhs();
1389: fprintf(f, "yyval.%s", tag);
1390: }
1391: else
1392: fprintf(f, "yyval");
1393: cptr += 2;
1394: goto loop;
1395: }
1396: else if (isdigit(cptr[1]))
1397: {
1398: ++cptr;
1399: i = get_number();
1400: if (ntags)
1401: {
1402: if (i <= 0 || i > n)
1403: unknown_rhs(i);
1404: tag = pitem[nitems + i - n - 1]->tag;
1405: if (tag == 0) untyped_rhs(i, pitem[nitems + i - n - 1]->name);
1406: fprintf(f, "yyvsp[%d].%s", i - n, tag);
1407: }
1408: else
1409: {
1410: if (i > n)
1411: dollar_warning(lineno, i);
1412: fprintf(f, "yyvsp[%d]", i - n);
1413: }
1414: goto loop;
1415: }
1416: else if (cptr[1] == '-')
1417: {
1418: cptr += 2;
1419: i = get_number();
1420: if (ntags)
1421: unknown_rhs(-i);
1422: fprintf(f, "yyvsp[%d]", -i - n);
1423: goto loop;
1424: }
1425: }
1426: if (isalpha(c) || c == '_' || c == '$')
1427: {
1428: do
1429: {
1430: putc(c, f);
1431: c = *++cptr;
1432: } while (isalnum(c) || c == '_' || c == '$');
1433: goto loop;
1434: }
1435: putc(c, f);
1436: ++cptr;
1437: switch (c)
1438: {
1439: case '\n':
1440: next_line:
1441: get_line();
1442: if (line) goto loop;
1443: unterminated_action(a_lineno, a_line, a_cptr);
1444:
1445: case ';':
1446: if (depth > 0) goto loop;
1447: fprintf(f, "\nbreak;\n");
1.6 deraadt 1448: FREE(a_line);
1.1 deraadt 1449: return;
1450:
1451: case '{':
1452: ++depth;
1453: goto loop;
1454:
1455: case '}':
1456: if (--depth > 0) goto loop;
1457: fprintf(f, "\nbreak;\n");
1.6 deraadt 1458: FREE(a_line);
1.1 deraadt 1459: return;
1460:
1461: case '\'':
1462: case '"':
1463: {
1464: int s_lineno = lineno;
1465: char *s_line = dup_line();
1466: char *s_cptr = s_line + (cptr - line - 1);
1467:
1468: quote = c;
1469: for (;;)
1470: {
1471: c = *cptr++;
1472: putc(c, f);
1473: if (c == quote)
1474: {
1475: FREE(s_line);
1476: goto loop;
1477: }
1478: if (c == '\n')
1479: unterminated_string(s_lineno, s_line, s_cptr);
1480: if (c == '\\')
1481: {
1482: c = *cptr++;
1483: putc(c, f);
1484: if (c == '\n')
1485: {
1486: get_line();
1487: if (line == 0)
1488: unterminated_string(s_lineno, s_line, s_cptr);
1489: }
1490: }
1491: }
1492: }
1493:
1494: case '/':
1495: c = *cptr;
1496: if (c == '/')
1497: {
1498: putc('*', f);
1499: while ((c = *++cptr) != '\n')
1500: {
1501: if (c == '*' && cptr[1] == '/')
1502: fprintf(f, "* ");
1503: else
1504: putc(c, f);
1505: }
1506: fprintf(f, "*/\n");
1507: goto next_line;
1508: }
1509: if (c == '*')
1510: {
1511: int c_lineno = lineno;
1512: char *c_line = dup_line();
1513: char *c_cptr = c_line + (cptr - line - 1);
1514:
1515: putc('*', f);
1516: ++cptr;
1517: for (;;)
1518: {
1519: c = *cptr++;
1520: putc(c, f);
1521: if (c == '*' && *cptr == '/')
1522: {
1523: putc('/', f);
1524: ++cptr;
1525: FREE(c_line);
1526: goto loop;
1527: }
1528: if (c == '\n')
1529: {
1530: get_line();
1531: if (line == 0)
1532: unterminated_comment(c_lineno, c_line, c_cptr);
1533: }
1534: }
1535: }
1536: goto loop;
1537:
1538: default:
1539: goto loop;
1540: }
1541: }
1542:
1543:
1544: int
1.15 pvalchev 1545: mark_symbol(void)
1.1 deraadt 1546: {
1.9 mpech 1547: int c;
1.18 pvalchev 1548: bucket *bp = NULL;
1.1 deraadt 1549:
1550: c = cptr[1];
1551: if (c == '%' || c == '\\')
1552: {
1553: cptr += 2;
1554: return (1);
1555: }
1556:
1557: if (c == '=')
1558: cptr += 2;
1559: else if ((c == 'p' || c == 'P') &&
1560: ((c = cptr[2]) == 'r' || c == 'R') &&
1561: ((c = cptr[3]) == 'e' || c == 'E') &&
1562: ((c = cptr[4]) == 'c' || c == 'C') &&
1563: ((c = cptr[5], !IS_IDENT(c))))
1564: cptr += 5;
1565: else
1566: syntax_error(lineno, line, cptr);
1567:
1568: c = nextc();
1569: if (isalpha(c) || c == '_' || c == '.' || c == '$')
1570: bp = get_name();
1571: else if (c == '\'' || c == '"')
1572: bp = get_literal();
1573: else
1574: {
1575: syntax_error(lineno, line, cptr);
1576: /*NOTREACHED*/
1577: }
1578:
1579: if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
1580: prec_redeclared();
1581:
1582: rprec[nrules] = bp->prec;
1583: rassoc[nrules] = bp->assoc;
1584: return (0);
1585: }
1586:
1587:
1.8 pvalchev 1588: void
1.15 pvalchev 1589: read_grammar(void)
1.1 deraadt 1590: {
1.9 mpech 1591: int c;
1.1 deraadt 1592:
1593: initialize_grammar();
1594: advance_to_start();
1595:
1596: for (;;)
1597: {
1598: c = nextc();
1599: if (c == EOF) break;
1600: if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' ||
1601: c == '"')
1602: add_symbol();
1603: else if (c == '{' || c == '=')
1604: copy_action();
1605: else if (c == '|')
1606: {
1607: end_rule();
1608: start_rule(plhs[nrules-1], 0);
1609: ++cptr;
1610: }
1611: else if (c == '%')
1612: {
1613: if (mark_symbol()) break;
1614: }
1615: else
1616: syntax_error(lineno, line, cptr);
1617: }
1618: end_rule();
1619: }
1620:
1621:
1.8 pvalchev 1622: void
1.15 pvalchev 1623: free_tags(void)
1.1 deraadt 1624: {
1.9 mpech 1625: int i;
1.1 deraadt 1626:
1627: if (tag_table == 0) return;
1628:
1629: for (i = 0; i < ntags; ++i)
1630: {
1631: assert(tag_table[i]);
1632: FREE(tag_table[i]);
1633: }
1634: FREE(tag_table);
1635: }
1636:
1637:
1.8 pvalchev 1638: void
1.15 pvalchev 1639: pack_names(void)
1.1 deraadt 1640: {
1.9 mpech 1641: bucket *bp;
1642: char *p, *s, *t;
1.1 deraadt 1643:
1644: name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
1645: for (bp = first_symbol; bp; bp = bp->next)
1646: name_pool_size += strlen(bp->name) + 1;
1647: name_pool = MALLOC(name_pool_size);
1648: if (name_pool == 0) no_space();
1649:
1.13 deraadt 1650: strlcpy(name_pool, "$accept", name_pool_size);
1651: strlcpy(name_pool+8, "$end", name_pool_size - 8);
1.1 deraadt 1652: t = name_pool + 13;
1653: for (bp = first_symbol; bp; bp = bp->next)
1654: {
1655: p = t;
1656: s = bp->name;
1.8 pvalchev 1657: while ((*t++ = *s++)) continue;
1.1 deraadt 1658: FREE(bp->name);
1659: bp->name = p;
1660: }
1661: }
1662:
1663:
1.8 pvalchev 1664: void
1.15 pvalchev 1665: check_symbols(void)
1.1 deraadt 1666: {
1.9 mpech 1667: bucket *bp;
1.1 deraadt 1668:
1669: if (goal->class == UNKNOWN)
1670: undefined_goal(goal->name);
1671:
1672: for (bp = first_symbol; bp; bp = bp->next)
1673: {
1674: if (bp->class == UNKNOWN)
1675: {
1676: undefined_symbol_warning(bp->name);
1677: bp->class = TERM;
1678: }
1679: }
1680: }
1681:
1682:
1.8 pvalchev 1683: void
1.15 pvalchev 1684: pack_symbols(void)
1.1 deraadt 1685: {
1.9 mpech 1686: bucket *bp;
1687: bucket **v;
1688: int i, j, k, n;
1.1 deraadt 1689:
1690: nsyms = 2;
1691: ntokens = 1;
1692: for (bp = first_symbol; bp; bp = bp->next)
1693: {
1694: ++nsyms;
1695: if (bp->class == TERM) ++ntokens;
1696: }
1697: start_symbol = ntokens;
1698: nvars = nsyms - ntokens;
1699:
1700: symbol_name = (char **) MALLOC(nsyms*sizeof(char *));
1701: if (symbol_name == 0) no_space();
1702: symbol_value = (short *) MALLOC(nsyms*sizeof(short));
1703: if (symbol_value == 0) no_space();
1704: symbol_prec = (short *) MALLOC(nsyms*sizeof(short));
1705: if (symbol_prec == 0) no_space();
1706: symbol_assoc = MALLOC(nsyms);
1707: if (symbol_assoc == 0) no_space();
1708:
1709: v = (bucket **) MALLOC(nsyms*sizeof(bucket *));
1710: if (v == 0) no_space();
1711:
1712: v[0] = 0;
1713: v[start_symbol] = 0;
1714:
1715: i = 1;
1716: j = start_symbol + 1;
1717: for (bp = first_symbol; bp; bp = bp->next)
1718: {
1719: if (bp->class == TERM)
1720: v[i++] = bp;
1721: else
1722: v[j++] = bp;
1723: }
1724: assert(i == ntokens && j == nsyms);
1725:
1726: for (i = 1; i < ntokens; ++i)
1727: v[i]->index = i;
1728:
1729: goal->index = start_symbol + 1;
1730: k = start_symbol + 2;
1731: while (++i < nsyms)
1732: if (v[i] != goal)
1733: {
1734: v[i]->index = k;
1735: ++k;
1736: }
1737:
1738: goal->value = 0;
1739: k = 1;
1740: for (i = start_symbol + 1; i < nsyms; ++i)
1741: {
1742: if (v[i] != goal)
1743: {
1744: v[i]->value = k;
1745: ++k;
1746: }
1747: }
1748:
1749: k = 0;
1750: for (i = 1; i < ntokens; ++i)
1751: {
1752: n = v[i]->value;
1753: if (n > 256)
1754: {
1755: for (j = k++; j > 0 && symbol_value[j-1] > n; --j)
1756: symbol_value[j] = symbol_value[j-1];
1757: symbol_value[j] = n;
1758: }
1759: }
1760:
1761: if (v[1]->value == UNDEFINED)
1762: v[1]->value = 256;
1763:
1764: j = 0;
1765: n = 257;
1766: for (i = 2; i < ntokens; ++i)
1767: {
1768: if (v[i]->value == UNDEFINED)
1769: {
1770: while (j < k && n == symbol_value[j])
1771: {
1772: while (++j < k && n == symbol_value[j]) continue;
1773: ++n;
1774: }
1775: v[i]->value = n;
1776: ++n;
1777: }
1778: }
1779:
1780: symbol_name[0] = name_pool + 8;
1781: symbol_value[0] = 0;
1782: symbol_prec[0] = 0;
1783: symbol_assoc[0] = TOKEN;
1784: for (i = 1; i < ntokens; ++i)
1785: {
1786: symbol_name[i] = v[i]->name;
1787: symbol_value[i] = v[i]->value;
1788: symbol_prec[i] = v[i]->prec;
1789: symbol_assoc[i] = v[i]->assoc;
1790: }
1791: symbol_name[start_symbol] = name_pool;
1792: symbol_value[start_symbol] = -1;
1793: symbol_prec[start_symbol] = 0;
1794: symbol_assoc[start_symbol] = TOKEN;
1795: for (++i; i < nsyms; ++i)
1796: {
1797: k = v[i]->index;
1798: symbol_name[k] = v[i]->name;
1799: symbol_value[k] = v[i]->value;
1800: symbol_prec[k] = v[i]->prec;
1801: symbol_assoc[k] = v[i]->assoc;
1802: }
1803:
1804: FREE(v);
1805: }
1806:
1807:
1.8 pvalchev 1808: void
1.15 pvalchev 1809: pack_grammar(void)
1.1 deraadt 1810: {
1.9 mpech 1811: int i, j;
1.1 deraadt 1812: int assoc, prec;
1813:
1814: ritem = (short *) MALLOC(nitems*sizeof(short));
1815: if (ritem == 0) no_space();
1816: rlhs = (short *) MALLOC(nrules*sizeof(short));
1817: if (rlhs == 0) no_space();
1818: rrhs = (short *) MALLOC((nrules+1)*sizeof(short));
1819: if (rrhs == 0) no_space();
1820: rprec = (short *) REALLOC(rprec, nrules*sizeof(short));
1821: if (rprec == 0) no_space();
1822: rassoc = REALLOC(rassoc, nrules);
1823: if (rassoc == 0) no_space();
1824:
1825: ritem[0] = -1;
1826: ritem[1] = goal->index;
1827: ritem[2] = 0;
1828: ritem[3] = -2;
1829: rlhs[0] = 0;
1830: rlhs[1] = 0;
1831: rlhs[2] = start_symbol;
1832: rrhs[0] = 0;
1833: rrhs[1] = 0;
1834: rrhs[2] = 1;
1835:
1836: j = 4;
1837: for (i = 3; i < nrules; ++i)
1838: {
1839: rlhs[i] = plhs[i]->index;
1840: rrhs[i] = j;
1841: assoc = TOKEN;
1842: prec = 0;
1843: while (pitem[j])
1844: {
1845: ritem[j] = pitem[j]->index;
1846: if (pitem[j]->class == TERM)
1847: {
1848: prec = pitem[j]->prec;
1849: assoc = pitem[j]->assoc;
1850: }
1851: ++j;
1852: }
1853: ritem[j] = -i;
1854: ++j;
1855: if (rprec[i] == UNDEFINED)
1856: {
1857: rprec[i] = prec;
1858: rassoc[i] = assoc;
1859: }
1860: }
1861: rrhs[i] = j;
1862:
1863: FREE(plhs);
1864: FREE(pitem);
1865: }
1866:
1867:
1.8 pvalchev 1868: void
1.15 pvalchev 1869: print_grammar(void)
1.1 deraadt 1870: {
1.9 mpech 1871: int i, j, k;
1.18 pvalchev 1872: int spacing = 0;
1.9 mpech 1873: FILE *f = verbose_file;
1.1 deraadt 1874:
1875: if (!vflag) return;
1876:
1877: k = 1;
1878: for (i = 2; i < nrules; ++i)
1879: {
1880: if (rlhs[i] != rlhs[i-1])
1881: {
1882: if (i != 2) fprintf(f, "\n");
1883: fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
1884: spacing = strlen(symbol_name[rlhs[i]]) + 1;
1885: }
1886: else
1887: {
1888: fprintf(f, "%4d ", i - 2);
1889: j = spacing;
1890: while (--j >= 0) putc(' ', f);
1891: putc('|', f);
1892: }
1893:
1894: while (ritem[k] >= 0)
1895: {
1896: fprintf(f, " %s", symbol_name[ritem[k]]);
1897: ++k;
1898: }
1899: ++k;
1900: putc('\n', f);
1901: }
1902: }
1903:
1904:
1.8 pvalchev 1905: void
1.15 pvalchev 1906: reader(void)
1.1 deraadt 1907: {
1908: write_section(banner);
1909: create_symbol_table();
1910: read_declarations();
1911: read_grammar();
1912: free_symbol_table();
1913: free_tags();
1914: pack_names();
1915: check_symbols();
1916: pack_symbols();
1917: pack_grammar();
1918: free_symbols();
1919: print_grammar();
1920: }