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