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