Annotation of src/usr.bin/yacc/reader.c, Revision 1.21
1.21 ! deraadt 1: /* $OpenBSD: reader.c,v 1.20 2006/04/21 07:38:16 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;
1123: pitem = (bucket **) MALLOC(maxitems*sizeof(bucket *));
1124: if (pitem == 0) no_space();
1125: pitem[0] = 0;
1126: pitem[1] = 0;
1127: pitem[2] = 0;
1128: pitem[3] = 0;
1129:
1130: nrules = 3;
1131: maxrules = 100;
1132: plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *));
1133: if (plhs == 0) no_space();
1134: plhs[0] = 0;
1135: plhs[1] = 0;
1136: plhs[2] = 0;
1137: rprec = (short *) MALLOC(maxrules*sizeof(short));
1138: if (rprec == 0) no_space();
1139: rprec[0] = 0;
1140: rprec[1] = 0;
1141: rprec[2] = 0;
1142: rassoc = (char *) MALLOC(maxrules*sizeof(char));
1143: if (rassoc == 0) no_space();
1144: rassoc[0] = TOKEN;
1145: rassoc[1] = TOKEN;
1146: rassoc[2] = TOKEN;
1147: }
1148:
1149:
1.8 pvalchev 1150: void
1.15 pvalchev 1151: expand_items(void)
1.1 deraadt 1152: {
1153: maxitems += 300;
1154: pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *));
1155: if (pitem == 0) no_space();
1156: }
1157:
1158:
1.8 pvalchev 1159: void
1.15 pvalchev 1160: expand_rules(void)
1.1 deraadt 1161: {
1162: maxrules += 100;
1163: plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *));
1164: if (plhs == 0) no_space();
1165: rprec = (short *) REALLOC(rprec, maxrules*sizeof(short));
1166: if (rprec == 0) no_space();
1167: rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char));
1168: if (rassoc == 0) no_space();
1169: }
1170:
1171:
1.8 pvalchev 1172: void
1.15 pvalchev 1173: advance_to_start(void)
1.1 deraadt 1174: {
1.9 mpech 1175: int c;
1176: bucket *bp;
1.1 deraadt 1177: char *s_cptr;
1178: int s_lineno;
1179:
1180: for (;;)
1181: {
1182: c = nextc();
1183: if (c != '%') break;
1184: s_cptr = cptr;
1185: switch (keyword())
1186: {
1187: case MARK:
1188: no_grammar();
1189:
1190: case TEXT:
1191: copy_text();
1192: break;
1193:
1194: case START:
1195: declare_start();
1196: break;
1197:
1198: default:
1199: syntax_error(lineno, line, s_cptr);
1200: }
1201: }
1202:
1203: c = nextc();
1204: if (!isalpha(c) && c != '_' && c != '.' && c != '_')
1205: syntax_error(lineno, line, cptr);
1206: bp = get_name();
1207: if (goal == 0)
1208: {
1209: if (bp->class == TERM)
1210: terminal_start(bp->name);
1211: goal = bp;
1212: }
1213:
1214: s_lineno = lineno;
1215: c = nextc();
1216: if (c == EOF) unexpected_EOF();
1217: if (c != ':') syntax_error(lineno, line, cptr);
1218: start_rule(bp, s_lineno);
1219: ++cptr;
1220: }
1221:
1222:
1.8 pvalchev 1223: void
1.15 pvalchev 1224: start_rule(bucket *bp, int s_lineno)
1.1 deraadt 1225: {
1226: if (bp->class == TERM)
1227: terminal_lhs(s_lineno);
1228: bp->class = NONTERM;
1229: if (nrules >= maxrules)
1230: expand_rules();
1231: plhs[nrules] = bp;
1232: rprec[nrules] = UNDEFINED;
1233: rassoc[nrules] = TOKEN;
1234: }
1235:
1236:
1.8 pvalchev 1237: void
1.15 pvalchev 1238: end_rule(void)
1.1 deraadt 1239: {
1.9 mpech 1240: int i;
1.1 deraadt 1241:
1242: if (!last_was_action && plhs[nrules]->tag)
1243: {
1244: for (i = nitems - 1; pitem[i]; --i) continue;
1.20 deraadt 1245: if (pitem[i+1] == 0 || pitem[i+1]->tag != plhs[nrules]->tag)
1.1 deraadt 1246: default_action_warning();
1247: }
1248:
1249: last_was_action = 0;
1250: if (nitems >= maxitems) expand_items();
1251: pitem[nitems] = 0;
1252: ++nitems;
1253: ++nrules;
1254: }
1255:
1256:
1.8 pvalchev 1257: void
1.15 pvalchev 1258: insert_empty_rule(void)
1.1 deraadt 1259: {
1.9 mpech 1260: bucket *bp, **bpp;
1.1 deraadt 1261:
1262: assert(cache);
1.12 deraadt 1263: snprintf(cache, cache_size, "$$%d", ++gensym);
1.1 deraadt 1264: bp = make_bucket(cache);
1265: last_symbol->next = bp;
1266: last_symbol = bp;
1267: bp->tag = plhs[nrules]->tag;
1268: bp->class = NONTERM;
1269:
1270: if ((nitems += 2) > maxitems)
1271: expand_items();
1272: bpp = pitem + nitems - 1;
1273: *bpp-- = bp;
1.8 pvalchev 1274: while ((bpp[0] = bpp[-1])) --bpp;
1.1 deraadt 1275:
1276: if (++nrules >= maxrules)
1277: expand_rules();
1278: plhs[nrules] = plhs[nrules-1];
1279: plhs[nrules-1] = bp;
1280: rprec[nrules] = rprec[nrules-1];
1281: rprec[nrules-1] = 0;
1282: rassoc[nrules] = rassoc[nrules-1];
1283: rassoc[nrules-1] = TOKEN;
1284: }
1285:
1286:
1.8 pvalchev 1287: void
1.15 pvalchev 1288: add_symbol(void)
1.1 deraadt 1289: {
1.9 mpech 1290: int c;
1291: bucket *bp;
1.1 deraadt 1292: int s_lineno = lineno;
1293:
1294: c = *cptr;
1295: if (c == '\'' || c == '"')
1296: bp = get_literal();
1297: else
1298: bp = get_name();
1299:
1300: c = nextc();
1301: if (c == ':')
1302: {
1303: end_rule();
1304: start_rule(bp, s_lineno);
1305: ++cptr;
1306: return;
1307: }
1308:
1309: if (last_was_action)
1310: insert_empty_rule();
1311: last_was_action = 0;
1312:
1313: if (++nitems > maxitems)
1314: expand_items();
1315: pitem[nitems-1] = bp;
1316: }
1317:
1318:
1.8 pvalchev 1319: void
1.15 pvalchev 1320: copy_action(void)
1.1 deraadt 1321: {
1.9 mpech 1322: int c;
1323: int i, n;
1.1 deraadt 1324: int depth;
1325: int quote;
1326: char *tag;
1.9 mpech 1327: FILE *f = action_file;
1.1 deraadt 1328: int a_lineno = lineno;
1329: char *a_line = dup_line();
1330: char *a_cptr = a_line + (cptr - line);
1331:
1332: if (last_was_action)
1333: insert_empty_rule();
1334: last_was_action = 1;
1335:
1336: fprintf(f, "case %d:\n", nrules - 2);
1337: if (!lflag)
1338: fprintf(f, line_format, lineno, input_file_name);
1339: if (*cptr == '=') ++cptr;
1340:
1341: n = 0;
1342: for (i = nitems - 1; pitem[i]; --i) ++n;
1343:
1344: depth = 0;
1345: loop:
1346: c = *cptr;
1347: if (c == '$')
1348: {
1349: if (cptr[1] == '<')
1350: {
1351: int d_lineno = lineno;
1352: char *d_line = dup_line();
1353: char *d_cptr = d_line + (cptr - line);
1354:
1355: ++cptr;
1356: tag = get_tag();
1357: c = *cptr;
1358: if (c == '$')
1359: {
1360: fprintf(f, "yyval.%s", tag);
1361: ++cptr;
1362: FREE(d_line);
1363: goto loop;
1364: }
1365: else if (isdigit(c))
1366: {
1367: i = get_number();
1368: if (i > n) dollar_warning(d_lineno, i);
1369: fprintf(f, "yyvsp[%d].%s", i - n, tag);
1370: FREE(d_line);
1371: goto loop;
1372: }
1373: else if (c == '-' && isdigit(cptr[1]))
1374: {
1375: ++cptr;
1376: i = -get_number() - n;
1377: fprintf(f, "yyvsp[%d].%s", i, tag);
1378: FREE(d_line);
1379: goto loop;
1380: }
1381: else
1382: dollar_error(d_lineno, d_line, d_cptr);
1383: }
1384: else if (cptr[1] == '$')
1385: {
1386: if (ntags)
1387: {
1388: tag = plhs[nrules]->tag;
1389: if (tag == 0) untyped_lhs();
1390: fprintf(f, "yyval.%s", tag);
1391: }
1392: else
1393: fprintf(f, "yyval");
1394: cptr += 2;
1395: goto loop;
1396: }
1397: else if (isdigit(cptr[1]))
1398: {
1399: ++cptr;
1400: i = get_number();
1401: if (ntags)
1402: {
1403: if (i <= 0 || i > n)
1404: unknown_rhs(i);
1405: tag = pitem[nitems + i - n - 1]->tag;
1406: if (tag == 0) untyped_rhs(i, pitem[nitems + i - n - 1]->name);
1407: fprintf(f, "yyvsp[%d].%s", i - n, tag);
1408: }
1409: else
1410: {
1411: if (i > n)
1412: dollar_warning(lineno, i);
1413: fprintf(f, "yyvsp[%d]", i - n);
1414: }
1415: goto loop;
1416: }
1417: else if (cptr[1] == '-')
1418: {
1419: cptr += 2;
1420: i = get_number();
1421: if (ntags)
1422: unknown_rhs(-i);
1423: fprintf(f, "yyvsp[%d]", -i - n);
1424: goto loop;
1425: }
1426: }
1427: if (isalpha(c) || c == '_' || c == '$')
1428: {
1429: do
1430: {
1431: putc(c, f);
1432: c = *++cptr;
1433: } while (isalnum(c) || c == '_' || c == '$');
1434: goto loop;
1435: }
1436: putc(c, f);
1437: ++cptr;
1438: switch (c)
1439: {
1440: case '\n':
1441: next_line:
1442: get_line();
1443: if (line) goto loop;
1444: unterminated_action(a_lineno, a_line, a_cptr);
1445:
1446: case ';':
1447: if (depth > 0) goto loop;
1448: fprintf(f, "\nbreak;\n");
1.6 deraadt 1449: FREE(a_line);
1.1 deraadt 1450: return;
1451:
1452: case '{':
1453: ++depth;
1454: goto loop;
1455:
1456: case '}':
1457: if (--depth > 0) goto loop;
1458: fprintf(f, "\nbreak;\n");
1.6 deraadt 1459: FREE(a_line);
1.1 deraadt 1460: return;
1461:
1462: case '\'':
1463: case '"':
1464: {
1465: int s_lineno = lineno;
1466: char *s_line = dup_line();
1467: char *s_cptr = s_line + (cptr - line - 1);
1468:
1469: quote = c;
1470: for (;;)
1471: {
1472: c = *cptr++;
1473: putc(c, f);
1474: if (c == quote)
1475: {
1476: FREE(s_line);
1477: goto loop;
1478: }
1479: if (c == '\n')
1480: unterminated_string(s_lineno, s_line, s_cptr);
1481: if (c == '\\')
1482: {
1483: c = *cptr++;
1484: putc(c, f);
1485: if (c == '\n')
1486: {
1487: get_line();
1488: if (line == 0)
1489: unterminated_string(s_lineno, s_line, s_cptr);
1490: }
1491: }
1492: }
1493: }
1494:
1495: case '/':
1496: c = *cptr;
1497: if (c == '/')
1498: {
1499: putc('*', f);
1500: while ((c = *++cptr) != '\n')
1501: {
1502: if (c == '*' && cptr[1] == '/')
1503: fprintf(f, "* ");
1504: else
1505: putc(c, f);
1506: }
1507: fprintf(f, "*/\n");
1508: goto next_line;
1509: }
1510: if (c == '*')
1511: {
1512: int c_lineno = lineno;
1513: char *c_line = dup_line();
1514: char *c_cptr = c_line + (cptr - line - 1);
1515:
1516: putc('*', f);
1517: ++cptr;
1518: for (;;)
1519: {
1520: c = *cptr++;
1521: putc(c, f);
1522: if (c == '*' && *cptr == '/')
1523: {
1524: putc('/', f);
1525: ++cptr;
1526: FREE(c_line);
1527: goto loop;
1528: }
1529: if (c == '\n')
1530: {
1531: get_line();
1532: if (line == 0)
1533: unterminated_comment(c_lineno, c_line, c_cptr);
1534: }
1535: }
1536: }
1537: goto loop;
1538:
1539: default:
1540: goto loop;
1541: }
1542: }
1543:
1544:
1545: int
1.15 pvalchev 1546: mark_symbol(void)
1.1 deraadt 1547: {
1.9 mpech 1548: int c;
1.18 pvalchev 1549: bucket *bp = NULL;
1.1 deraadt 1550:
1551: c = cptr[1];
1552: if (c == '%' || c == '\\')
1553: {
1554: cptr += 2;
1555: return (1);
1556: }
1557:
1558: if (c == '=')
1559: cptr += 2;
1560: else if ((c == 'p' || c == 'P') &&
1561: ((c = cptr[2]) == 'r' || c == 'R') &&
1562: ((c = cptr[3]) == 'e' || c == 'E') &&
1563: ((c = cptr[4]) == 'c' || c == 'C') &&
1564: ((c = cptr[5], !IS_IDENT(c))))
1565: cptr += 5;
1566: else
1567: syntax_error(lineno, line, cptr);
1568:
1569: c = nextc();
1570: if (isalpha(c) || c == '_' || c == '.' || c == '$')
1571: bp = get_name();
1572: else if (c == '\'' || c == '"')
1573: bp = get_literal();
1574: else
1575: {
1576: syntax_error(lineno, line, cptr);
1577: /*NOTREACHED*/
1578: }
1579:
1580: if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
1581: prec_redeclared();
1582:
1583: rprec[nrules] = bp->prec;
1584: rassoc[nrules] = bp->assoc;
1585: return (0);
1586: }
1587:
1588:
1.8 pvalchev 1589: void
1.15 pvalchev 1590: read_grammar(void)
1.1 deraadt 1591: {
1.9 mpech 1592: int c;
1.1 deraadt 1593:
1594: initialize_grammar();
1595: advance_to_start();
1596:
1597: for (;;)
1598: {
1599: c = nextc();
1600: if (c == EOF) break;
1601: if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' ||
1602: c == '"')
1603: add_symbol();
1604: else if (c == '{' || c == '=')
1605: copy_action();
1606: else if (c == '|')
1607: {
1608: end_rule();
1609: start_rule(plhs[nrules-1], 0);
1610: ++cptr;
1611: }
1612: else if (c == '%')
1613: {
1614: if (mark_symbol()) break;
1615: }
1616: else
1617: syntax_error(lineno, line, cptr);
1618: }
1619: end_rule();
1620: }
1621:
1622:
1.8 pvalchev 1623: void
1.15 pvalchev 1624: free_tags(void)
1.1 deraadt 1625: {
1.9 mpech 1626: int i;
1.1 deraadt 1627:
1628: if (tag_table == 0) return;
1629:
1630: for (i = 0; i < ntags; ++i)
1631: {
1632: assert(tag_table[i]);
1633: FREE(tag_table[i]);
1634: }
1635: FREE(tag_table);
1636: }
1637:
1638:
1.8 pvalchev 1639: void
1.15 pvalchev 1640: pack_names(void)
1.1 deraadt 1641: {
1.9 mpech 1642: bucket *bp;
1643: char *p, *s, *t;
1.1 deraadt 1644:
1645: name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
1646: for (bp = first_symbol; bp; bp = bp->next)
1647: name_pool_size += strlen(bp->name) + 1;
1648: name_pool = MALLOC(name_pool_size);
1649: if (name_pool == 0) no_space();
1650:
1.13 deraadt 1651: strlcpy(name_pool, "$accept", name_pool_size);
1652: strlcpy(name_pool+8, "$end", name_pool_size - 8);
1.1 deraadt 1653: t = name_pool + 13;
1654: for (bp = first_symbol; bp; bp = bp->next)
1655: {
1656: p = t;
1657: s = bp->name;
1.8 pvalchev 1658: while ((*t++ = *s++)) continue;
1.1 deraadt 1659: FREE(bp->name);
1660: bp->name = p;
1661: }
1662: }
1663:
1664:
1.8 pvalchev 1665: void
1.15 pvalchev 1666: check_symbols(void)
1.1 deraadt 1667: {
1.9 mpech 1668: bucket *bp;
1.1 deraadt 1669:
1670: if (goal->class == UNKNOWN)
1671: undefined_goal(goal->name);
1672:
1673: for (bp = first_symbol; bp; bp = bp->next)
1674: {
1675: if (bp->class == UNKNOWN)
1676: {
1677: undefined_symbol_warning(bp->name);
1678: bp->class = TERM;
1679: }
1680: }
1681: }
1682:
1683:
1.8 pvalchev 1684: void
1.15 pvalchev 1685: pack_symbols(void)
1.1 deraadt 1686: {
1.9 mpech 1687: bucket *bp;
1688: bucket **v;
1689: int i, j, k, n;
1.1 deraadt 1690:
1691: nsyms = 2;
1692: ntokens = 1;
1693: for (bp = first_symbol; bp; bp = bp->next)
1694: {
1695: ++nsyms;
1696: if (bp->class == TERM) ++ntokens;
1697: }
1698: start_symbol = ntokens;
1699: nvars = nsyms - ntokens;
1700:
1701: symbol_name = (char **) MALLOC(nsyms*sizeof(char *));
1702: if (symbol_name == 0) no_space();
1703: symbol_value = (short *) MALLOC(nsyms*sizeof(short));
1704: if (symbol_value == 0) no_space();
1705: symbol_prec = (short *) MALLOC(nsyms*sizeof(short));
1706: if (symbol_prec == 0) no_space();
1707: symbol_assoc = MALLOC(nsyms);
1708: if (symbol_assoc == 0) no_space();
1709:
1710: v = (bucket **) MALLOC(nsyms*sizeof(bucket *));
1711: if (v == 0) no_space();
1712:
1713: v[0] = 0;
1714: v[start_symbol] = 0;
1715:
1716: i = 1;
1717: j = start_symbol + 1;
1718: for (bp = first_symbol; bp; bp = bp->next)
1719: {
1720: if (bp->class == TERM)
1721: v[i++] = bp;
1722: else
1723: v[j++] = bp;
1724: }
1725: assert(i == ntokens && j == nsyms);
1726:
1727: for (i = 1; i < ntokens; ++i)
1728: v[i]->index = i;
1729:
1730: goal->index = start_symbol + 1;
1731: k = start_symbol + 2;
1732: while (++i < nsyms)
1733: if (v[i] != goal)
1734: {
1735: v[i]->index = k;
1736: ++k;
1737: }
1738:
1739: goal->value = 0;
1740: k = 1;
1741: for (i = start_symbol + 1; i < nsyms; ++i)
1742: {
1743: if (v[i] != goal)
1744: {
1745: v[i]->value = k;
1746: ++k;
1747: }
1748: }
1749:
1750: k = 0;
1751: for (i = 1; i < ntokens; ++i)
1752: {
1753: n = v[i]->value;
1754: if (n > 256)
1755: {
1756: for (j = k++; j > 0 && symbol_value[j-1] > n; --j)
1757: symbol_value[j] = symbol_value[j-1];
1758: symbol_value[j] = n;
1759: }
1760: }
1761:
1762: if (v[1]->value == UNDEFINED)
1763: v[1]->value = 256;
1764:
1765: j = 0;
1766: n = 257;
1767: for (i = 2; i < ntokens; ++i)
1768: {
1769: if (v[i]->value == UNDEFINED)
1770: {
1771: while (j < k && n == symbol_value[j])
1772: {
1773: while (++j < k && n == symbol_value[j]) continue;
1774: ++n;
1775: }
1776: v[i]->value = n;
1777: ++n;
1778: }
1779: }
1780:
1781: symbol_name[0] = name_pool + 8;
1782: symbol_value[0] = 0;
1783: symbol_prec[0] = 0;
1784: symbol_assoc[0] = TOKEN;
1785: for (i = 1; i < ntokens; ++i)
1786: {
1787: symbol_name[i] = v[i]->name;
1788: symbol_value[i] = v[i]->value;
1789: symbol_prec[i] = v[i]->prec;
1790: symbol_assoc[i] = v[i]->assoc;
1791: }
1792: symbol_name[start_symbol] = name_pool;
1793: symbol_value[start_symbol] = -1;
1794: symbol_prec[start_symbol] = 0;
1795: symbol_assoc[start_symbol] = TOKEN;
1796: for (++i; i < nsyms; ++i)
1797: {
1798: k = v[i]->index;
1799: symbol_name[k] = v[i]->name;
1800: symbol_value[k] = v[i]->value;
1801: symbol_prec[k] = v[i]->prec;
1802: symbol_assoc[k] = v[i]->assoc;
1803: }
1804:
1805: FREE(v);
1806: }
1807:
1808:
1.8 pvalchev 1809: void
1.15 pvalchev 1810: pack_grammar(void)
1.1 deraadt 1811: {
1.9 mpech 1812: int i, j;
1.1 deraadt 1813: int assoc, prec;
1814:
1815: ritem = (short *) MALLOC(nitems*sizeof(short));
1816: if (ritem == 0) no_space();
1817: rlhs = (short *) MALLOC(nrules*sizeof(short));
1818: if (rlhs == 0) no_space();
1819: rrhs = (short *) MALLOC((nrules+1)*sizeof(short));
1820: if (rrhs == 0) no_space();
1821: rprec = (short *) REALLOC(rprec, nrules*sizeof(short));
1822: if (rprec == 0) no_space();
1823: rassoc = REALLOC(rassoc, nrules);
1824: if (rassoc == 0) no_space();
1825:
1826: ritem[0] = -1;
1827: ritem[1] = goal->index;
1828: ritem[2] = 0;
1829: ritem[3] = -2;
1830: rlhs[0] = 0;
1831: rlhs[1] = 0;
1832: rlhs[2] = start_symbol;
1833: rrhs[0] = 0;
1834: rrhs[1] = 0;
1835: rrhs[2] = 1;
1836:
1837: j = 4;
1838: for (i = 3; i < nrules; ++i)
1839: {
1840: rlhs[i] = plhs[i]->index;
1841: rrhs[i] = j;
1842: assoc = TOKEN;
1843: prec = 0;
1844: while (pitem[j])
1845: {
1846: ritem[j] = pitem[j]->index;
1847: if (pitem[j]->class == TERM)
1848: {
1849: prec = pitem[j]->prec;
1850: assoc = pitem[j]->assoc;
1851: }
1852: ++j;
1853: }
1854: ritem[j] = -i;
1855: ++j;
1856: if (rprec[i] == UNDEFINED)
1857: {
1858: rprec[i] = prec;
1859: rassoc[i] = assoc;
1860: }
1861: }
1862: rrhs[i] = j;
1863:
1864: FREE(plhs);
1865: FREE(pitem);
1866: }
1867:
1868:
1.8 pvalchev 1869: void
1.15 pvalchev 1870: print_grammar(void)
1.1 deraadt 1871: {
1.9 mpech 1872: int i, j, k;
1.18 pvalchev 1873: int spacing = 0;
1.9 mpech 1874: FILE *f = verbose_file;
1.1 deraadt 1875:
1876: if (!vflag) return;
1877:
1878: k = 1;
1879: for (i = 2; i < nrules; ++i)
1880: {
1881: if (rlhs[i] != rlhs[i-1])
1882: {
1883: if (i != 2) fprintf(f, "\n");
1884: fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
1885: spacing = strlen(symbol_name[rlhs[i]]) + 1;
1886: }
1887: else
1888: {
1889: fprintf(f, "%4d ", i - 2);
1890: j = spacing;
1891: while (--j >= 0) putc(' ', f);
1892: putc('|', f);
1893: }
1894:
1895: while (ritem[k] >= 0)
1896: {
1897: fprintf(f, " %s", symbol_name[ritem[k]]);
1898: ++k;
1899: }
1900: ++k;
1901: putc('\n', f);
1902: }
1903: }
1904:
1905:
1.8 pvalchev 1906: void
1.15 pvalchev 1907: reader(void)
1.1 deraadt 1908: {
1909: write_section(banner);
1910: create_symbol_table();
1911: read_declarations();
1912: read_grammar();
1913: free_symbol_table();
1914: free_tags();
1915: pack_names();
1916: check_symbols();
1917: pack_symbols();
1918: pack_grammar();
1919: free_symbols();
1920: print_grammar();
1921: }