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