Remove building with NOCRYPTO option
[minix3.git] / external / bsd / byacc / dist / reader.c
blob6292990b3180a8bfd26698ca7df17d507a08f8e3
1 /* $NetBSD: reader.c,v 1.12 2015/01/04 19:30:26 joerg Exp $ */
3 /* Id: reader.c,v 1.58 2014/10/06 22:15:08 tom Exp */
5 #include "defs.h"
7 #include <sys/cdefs.h>
8 __RCSID("$NetBSD: reader.c,v 1.12 2015/01/04 19:30:26 joerg Exp $");
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. */
15 #define LINESIZE 100
17 #define L_CURL '{'
18 #define R_CURL '}'
19 #define L_PAREN '('
20 #define R_PAREN ')'
21 #define L_BRAC '['
22 #define R_BRAC ']'
24 /* the maximum number of arguments (inherited attributes) to a non-terminal */
25 /* this is a hard limit, but seems more than adequate */
26 #define MAXARGS 20
28 static void start_rule(bucket *bp, int s_lineno);
29 #if defined(YYBTYACC)
30 static void copy_initial_action(void);
31 static void copy_destructor(void);
32 static char *process_destructor_XX(char *code, char *tag);
33 #endif
35 static char *cache;
36 static int cinc, cache_size;
38 int ntags;
39 static int tagmax, havetags;
40 static char **tag_table;
42 static char saw_eof;
43 char unionized;
44 char *cptr, *line;
45 static int linesize;
47 static bucket *goal;
48 static Value_t prec;
49 static int gensym;
50 static char last_was_action;
52 static int maxitems;
53 static bucket **pitem;
55 static int maxrules;
56 static bucket **plhs;
58 static size_t name_pool_size;
59 static char *name_pool;
61 char line_format[] = "#line %d \"%s\"\n";
63 param *lex_param;
64 param *parse_param;
66 #if defined(YYBTYACC)
67 int destructor = 0; /* =1 if at least one %destructor */
69 static bucket *default_destructor[3] =
70 {0, 0, 0};
72 #define UNTYPED_DEFAULT 0
73 #define TYPED_DEFAULT 1
74 #define TYPE_SPECIFIED 2
76 static bucket *
77 lookup_type_destructor(char *tag)
79 const char fmt[] = "%.*s destructor";
80 char name[1024] = "\0";
81 bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED];
83 while ((bp = *bpp) != NULL)
85 if (bp->tag == tag)
86 return (bp);
87 bpp = &bp->link;
90 sprintf(name, fmt, (int)(sizeof(name) - sizeof(fmt)), tag);
91 *bpp = bp = make_bucket(name);
92 bp->tag = tag;
94 return (bp);
96 #endif /* defined(YYBTYACC) */
98 static void
99 cachec(int c)
101 assert(cinc >= 0);
102 if (cinc >= cache_size)
104 cache_size += 256;
105 cache = TREALLOC(char, cache, cache_size);
106 NO_SPACE(cache);
108 cache[cinc] = (char)c;
109 ++cinc;
112 static void
113 get_line(void)
115 FILE *f = input_file;
116 int c;
117 int i;
119 if (saw_eof || (c = getc(f)) == EOF)
121 if (line)
123 FREE(line);
124 line = 0;
126 cptr = 0;
127 saw_eof = 1;
128 return;
131 if (line == 0 || linesize != (LINESIZE + 1))
133 if (line)
134 FREE(line);
135 linesize = LINESIZE + 1;
136 line = TMALLOC(char, linesize);
137 NO_SPACE(line);
140 i = 0;
141 ++lineno;
142 for (;;)
144 line[i++] = (char)c;
145 if (c == '\n')
146 break;
147 if ((i + 3) >= linesize)
149 linesize += LINESIZE;
150 line = TREALLOC(char, line, linesize);
151 NO_SPACE(line);
153 c = getc(f);
154 if (c == EOF)
156 line[i++] = '\n';
157 saw_eof = 1;
158 break;
161 line[i] = '\0';
162 cptr = line;
163 return;
166 static char *
167 dup_line(void)
169 char *p, *s, *t;
171 if (line == 0)
172 return (0);
173 s = line;
174 while (*s != '\n')
175 ++s;
176 p = TMALLOC(char, s - line + 1);
177 NO_SPACE(p);
179 s = line;
180 t = p;
181 while ((*t++ = *s++) != '\n')
182 continue;
183 return (p);
186 static void
187 skip_comment(void)
189 char *s;
190 struct ainfo a;
191 a.a_lineno = lineno;
192 a.a_line = dup_line();
193 a.a_cptr = a.a_line + (cptr - line);
195 s = cptr + 2;
196 for (;;)
198 if (*s == '*' && s[1] == '/')
200 cptr = s + 2;
201 FREE(a.a_line);
202 return;
204 if (*s == '\n')
206 get_line();
207 if (line == 0)
208 unterminated_comment(&a);
209 s = cptr;
211 else
212 ++s;
216 static int
217 next_inline(void)
219 char *s;
221 if (line == 0)
223 get_line();
224 if (line == 0)
225 return (EOF);
228 s = cptr;
229 for (;;)
231 switch (*s)
233 case '/':
234 if (s[1] == '*')
236 cptr = s;
237 skip_comment();
238 s = cptr;
239 break;
241 else if (s[1] == '/')
243 get_line();
244 if (line == 0)
245 return (EOF);
246 s = cptr;
247 break;
249 /* FALLTHRU */
251 default:
252 cptr = s;
253 return (*s);
258 static int
259 nextc(void)
261 int ch;
262 int finish = 0;
266 switch (ch = next_inline())
268 case '\n':
269 get_line();
270 break;
271 case ' ':
272 case '\t':
273 case '\f':
274 case '\r':
275 case '\v':
276 case ',':
277 case ';':
278 ++cptr;
279 break;
280 case '\\':
281 ch = '%';
282 /* FALLTHRU */
283 default:
284 finish = 1;
285 break;
288 while (!finish);
290 return ch;
292 /* *INDENT-OFF* */
293 static struct keyword
295 char name[14];
296 int token;
298 keywords[] = {
299 { "binary", NONASSOC },
300 { "debug", XXXDEBUG },
301 #if defined(YYBTYACC)
302 { "destructor", DESTRUCTOR },
303 #endif
304 { "error-verbose",ERROR_VERBOSE },
305 { "expect", EXPECT },
306 { "expect-rr", EXPECT_RR },
307 { "ident", IDENT },
308 #if defined(YYBTYACC)
309 { "initial-action", INITIAL_ACTION },
310 #endif
311 { "left", LEFT },
312 { "lex-param", LEX_PARAM },
313 #if defined(YYBTYACC)
314 { "locations", LOCATIONS },
315 #endif
316 { "nonassoc", NONASSOC },
317 { "parse-param", PARSE_PARAM },
318 { "pure-parser", PURE_PARSER },
319 { "right", RIGHT },
320 { "start", START },
321 { "term", TOKEN },
322 { "token", TOKEN },
323 { "token-table", TOKEN_TABLE },
324 { "type", TYPE },
325 { "union", UNION },
326 { "yacc", POSIX_YACC },
328 /* *INDENT-ON* */
330 static int
331 compare_keys(const void *a, const void *b)
333 const struct keyword *p = (const struct keyword *)a;
334 const struct keyword *q = (const struct keyword *)b;
335 return strcmp(p->name, q->name);
338 static int
339 keyword(void)
341 int c;
342 char *t_cptr = cptr;
343 struct keyword *key;
345 c = *++cptr;
346 if (isalpha(c))
348 cinc = 0;
349 for (;;)
351 if (isalpha(c))
353 if (isupper(c))
354 c = tolower(c);
355 cachec(c);
357 else if (isdigit(c)
358 || c == '-'
359 || c == '.'
360 || c == '$')
362 cachec(c);
364 else if (c == '_')
366 /* treat keywords spelled with '_' as if it were '-' */
367 cachec('-');
369 else
371 break;
373 c = *++cptr;
375 cachec(NUL);
377 if ((key = bsearch(cache, keywords,
378 sizeof(keywords) / sizeof(*key),
379 sizeof(*key), compare_keys)))
380 return key->token;
382 else
384 ++cptr;
385 if (c == L_CURL)
386 return (TEXT);
387 if (c == '%' || c == '\\')
388 return (MARK);
389 if (c == '<')
390 return (LEFT);
391 if (c == '>')
392 return (RIGHT);
393 if (c == '0')
394 return (TOKEN);
395 if (c == '2')
396 return (NONASSOC);
398 syntax_error(lineno, line, t_cptr);
402 static void
403 copy_ident(void)
405 int c;
406 FILE *f = output_file;
408 c = nextc();
409 if (c == EOF)
410 unexpected_EOF();
411 if (c != '"')
412 syntax_error(lineno, line, cptr);
413 ++outline;
414 fprintf(f, "#ident \"");
415 for (;;)
417 c = *++cptr;
418 if (c == '\n')
420 fprintf(f, "\"\n");
421 return;
423 putc(c, f);
424 if (c == '"')
426 putc('\n', f);
427 ++cptr;
428 return;
433 static char *
434 copy_string(int quote)
436 struct mstring *temp = msnew();
437 int c;
438 struct ainfo a;
439 a.a_lineno = lineno;
440 a.a_line = dup_line();
441 a.a_cptr = a.a_line + (cptr - line - 1);
443 for (;;)
445 c = *cptr++;
446 mputc(temp, c);
447 if (c == quote)
449 FREE(a.a_line);
450 return msdone(temp);
452 if (c == '\n')
453 unterminated_string(&a);
454 if (c == '\\')
456 c = *cptr++;
457 mputc(temp, c);
458 if (c == '\n')
460 get_line();
461 if (line == 0)
462 unterminated_string(&a);
468 static char *
469 copy_comment(void)
471 struct mstring *temp = msnew();
472 int c;
474 c = *cptr;
475 if (c == '/')
477 mputc(temp, '*');
478 while ((c = *++cptr) != '\n')
480 mputc(temp, c);
481 if (c == '*' && cptr[1] == '/')
482 mputc(temp, ' ');
484 mputc(temp, '*');
485 mputc(temp, '/');
487 else if (c == '*')
489 struct ainfo a;
490 a.a_lineno = lineno;
491 a.a_line = dup_line();
492 a.a_cptr = a.a_line + (cptr - line - 1);
494 mputc(temp, c);
495 ++cptr;
496 for (;;)
498 c = *cptr++;
499 mputc(temp, c);
500 if (c == '*' && *cptr == '/')
502 mputc(temp, '/');
503 ++cptr;
504 FREE(a.a_line);
505 return msdone(temp);
507 if (c == '\n')
509 get_line();
510 if (line == 0)
511 unterminated_comment(&a);
515 return msdone(temp);
518 static void
519 copy_text(void)
521 int c;
522 FILE *f = text_file;
523 int need_newline = 0;
524 struct ainfo a;
525 a.a_lineno = lineno;
526 a.a_line = dup_line();
527 a.a_cptr = a.a_line + (cptr - line - 2);
529 if (*cptr == '\n')
531 get_line();
532 if (line == 0)
533 unterminated_text(&a);
535 if (!lflag)
536 fprintf(f, line_format, lineno, input_file_name);
538 loop:
539 c = *cptr++;
540 switch (c)
542 case '\n':
543 putc('\n', f);
544 need_newline = 0;
545 get_line();
546 if (line)
547 goto loop;
548 unterminated_text(&a);
550 case '\'':
551 case '"':
552 putc(c, f);
554 char *s = copy_string(c);
555 fputs(s, f);
556 free(s);
558 need_newline = 1;
559 goto loop;
561 case '/':
562 putc(c, f);
564 char *s = copy_comment();
565 fputs(s, f);
566 free(s);
568 need_newline = 1;
569 goto loop;
571 case '%':
572 case '\\':
573 if (*cptr == R_CURL)
575 if (need_newline)
576 putc('\n', f);
577 ++cptr;
578 FREE(a.a_line);
579 return;
581 /* FALLTHRU */
583 default:
584 putc(c, f);
585 need_newline = 1;
586 goto loop;
590 static void
591 puts_both(const char *s)
593 fputs(s, text_file);
594 if (dflag)
595 fputs(s, union_file);
598 static void
599 putc_both(int c)
601 putc(c, text_file);
602 if (dflag)
603 putc(c, union_file);
606 static void
607 copy_union(void)
609 int c;
610 int depth;
611 struct ainfo a;
612 a.a_lineno = lineno;
613 a.a_line = dup_line();
614 a.a_cptr = a.a_line + (cptr - line - 6);
616 if (unionized)
617 over_unionized(cptr - 6);
618 unionized = 1;
620 if (!lflag)
621 fprintf(text_file, line_format, lineno, input_file_name);
623 puts_both("#ifdef YYSTYPE\n");
624 puts_both("#undef YYSTYPE_IS_DECLARED\n");
625 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
626 puts_both("#endif\n");
627 puts_both("#ifndef YYSTYPE_IS_DECLARED\n");
628 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
629 puts_both("typedef union");
631 depth = 0;
632 loop:
633 c = *cptr++;
634 putc_both(c);
635 switch (c)
637 case '\n':
638 get_line();
639 if (line == 0)
640 unterminated_union(&a);
641 goto loop;
643 case L_CURL:
644 ++depth;
645 goto loop;
647 case R_CURL:
648 if (--depth == 0)
650 puts_both(" YYSTYPE;\n");
651 puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n");
652 FREE(a.a_line);
653 return;
655 goto loop;
657 case '\'':
658 case '"':
660 char *s = copy_string(c);
661 puts_both(s);
662 free(s);
664 goto loop;
666 case '/':
668 char *s = copy_comment();
669 puts_both(s);
670 free(s);
672 goto loop;
674 default:
675 goto loop;
679 static char *
680 after_blanks(char *s)
682 while (*s != '\0' && isspace(UCH(*s)))
683 ++s;
684 return s;
688 * Trim leading/trailing blanks, and collapse multiple embedded blanks to a
689 * single space. Return index to last character in the buffer.
691 static int
692 trim_blanks(char *buffer)
694 if (*buffer != '\0')
696 char *d = buffer;
697 char *s = after_blanks(d);
699 while ((*d++ = *s++) != '\0')
704 --d;
705 while ((--d != buffer) && isspace(UCH(*d)))
706 *d = '\0';
708 for (s = d = buffer; (*d++ = *s++) != '\0';)
710 if (isspace(UCH(*s)))
712 *s = ' ';
713 while (isspace(UCH(*s)))
715 *s++ = ' ';
717 --s;
722 return (int)strlen(buffer) - 1;
726 * Scan forward in the current line-buffer looking for a right-curly bracket.
728 * Parameters begin with a left-curly bracket, and continue until there are no
729 * more interesting characters after the last right-curly bracket on the
730 * current line. Bison documents parameters as separated like this:
731 * {type param1} {type2 param2}
732 * but also accepts commas (although some versions of bison mishandle this)
733 * {type param1, type2 param2}
735 static int
736 more_curly(void)
738 char *save = cptr;
739 int result = 0;
740 int finish = 0;
743 switch (next_inline())
745 case 0:
746 case '\n':
747 finish = 1;
748 break;
749 case R_CURL:
750 finish = 1;
751 result = 1;
752 break;
754 ++cptr;
756 while (!finish);
757 cptr = save;
758 return result;
761 static void
762 save_param(int k, char *buffer, int name, int type2)
764 param *head, *p;
766 p = TMALLOC(param, 1);
767 NO_SPACE(p);
769 p->type2 = strdup(buffer + type2);
770 NO_SPACE(p->type2);
771 buffer[type2] = '\0';
772 (void)trim_blanks(p->type2);
774 p->name = strdup(buffer + name);
775 NO_SPACE(p->name);
776 buffer[name] = '\0';
777 (void)trim_blanks(p->name);
779 p->type = strdup(buffer);
780 NO_SPACE(p->type);
781 (void)trim_blanks(p->type);
783 if (k == LEX_PARAM)
784 head = lex_param;
785 else
786 head = parse_param;
788 if (head != NULL)
790 while (head->next)
791 head = head->next;
792 head->next = p;
794 else
796 if (k == LEX_PARAM)
797 lex_param = p;
798 else
799 parse_param = p;
801 p->next = NULL;
805 * Keep a linked list of parameters. This may be multi-line, if the trailing
806 * right-curly bracket is absent.
808 static void
809 copy_param(int k)
811 int c;
812 int name, type2;
813 int curly = 0;
814 char *buf = 0;
815 int i = -1;
816 size_t buf_size = 0;
817 int st_lineno = lineno;
818 char *comma;
822 int state = curly;
823 c = next_inline();
824 switch (c)
826 case EOF:
827 unexpected_EOF();
828 break;
829 case L_CURL:
830 if (curly == 1)
832 goto oops;
834 curly = 1;
835 st_lineno = lineno;
836 break;
837 case R_CURL:
838 if (curly != 1)
840 goto oops;
842 curly = 2;
843 break;
844 case '\n':
845 if (curly == 0)
847 goto oops;
849 break;
850 case '%':
851 if ((curly == 1) && (cptr == line))
853 lineno = st_lineno;
854 missing_brace();
856 /* FALLTHRU */
857 case '"':
858 case '\'':
859 goto oops;
860 default:
861 if (curly == 0 && !isspace(UCH(c)))
863 goto oops;
865 break;
867 if (buf == 0)
869 buf_size = (size_t) linesize;
870 buf = TMALLOC(char, buf_size);
872 else if (c == '\n')
874 get_line();
875 if (line == 0)
876 unexpected_EOF();
877 --cptr;
878 buf_size += (size_t) linesize;
879 buf = TREALLOC(char, buf, buf_size);
881 NO_SPACE(buf);
882 if (curly)
884 if ((state == 2) && (c == L_CURL))
886 buf[++i] = ',';
888 else if ((state == 2) && isspace(UCH(c)))
892 else if ((c != L_CURL) && (c != R_CURL))
894 buf[++i] = (char)c;
897 cptr++;
899 while (curly < 2 || more_curly());
901 if (i == 0)
903 if (curly == 1)
905 lineno = st_lineno;
906 missing_brace();
908 goto oops;
911 buf[++i] = '\0';
912 i = trim_blanks(buf);
914 comma = buf - 1;
917 char *parms = (comma + 1);
918 comma = strchr(parms, ',');
919 if (comma != 0)
920 *comma = '\0';
922 (void)trim_blanks(parms);
923 i = (int)strlen(parms) - 1;
924 if (i < 0)
926 goto oops;
929 if (parms[i] == ']')
931 int level = 1;
932 while (i >= 0 && level > 0 && parms[i] != '[')
934 if (parms[i] == ']')
935 ++level;
936 else if (parms[i] == '[')
937 --level;
938 i--;
940 if (i <= 0)
941 unexpected_EOF();
942 type2 = i--;
944 else
946 type2 = i + 1;
949 while (i > 0 && (isalnum(UCH(parms[i])) || UCH(parms[i]) == '_'))
950 i--;
952 if (!isspace(UCH(parms[i])) && parms[i] != '*')
953 goto oops;
955 name = i + 1;
957 save_param(k, parms, name, type2);
959 while (comma != 0);
960 FREE(buf);
961 return;
963 oops:
964 FREE(buf);
965 syntax_error(lineno, line, cptr);
968 static int
969 hexval(int c)
971 if (c >= '0' && c <= '9')
972 return (c - '0');
973 if (c >= 'A' && c <= 'F')
974 return (c - 'A' + 10);
975 if (c >= 'a' && c <= 'f')
976 return (c - 'a' + 10);
977 return (-1);
980 static bucket *
981 get_literal(void)
983 int c, quote;
984 int i;
985 int n;
986 char *s;
987 bucket *bp;
988 struct ainfo a;
989 a.a_lineno = lineno;
990 a.a_line = dup_line();
991 a.a_cptr = a.a_line + (cptr - line);
993 quote = *cptr++;
994 cinc = 0;
995 for (;;)
997 c = *cptr++;
998 if (c == quote)
999 break;
1000 if (c == '\n')
1001 unterminated_string(&a);
1002 if (c == '\\')
1004 char *c_cptr = cptr - 1;
1006 c = *cptr++;
1007 switch (c)
1009 case '\n':
1010 get_line();
1011 if (line == 0)
1012 unterminated_string(&a);
1013 continue;
1015 case '0':
1016 case '1':
1017 case '2':
1018 case '3':
1019 case '4':
1020 case '5':
1021 case '6':
1022 case '7':
1023 n = c - '0';
1024 c = *cptr;
1025 if (IS_OCTAL(c))
1027 n = (n << 3) + (c - '0');
1028 c = *++cptr;
1029 if (IS_OCTAL(c))
1031 n = (n << 3) + (c - '0');
1032 ++cptr;
1035 if (n > MAXCHAR)
1036 illegal_character(c_cptr);
1037 c = n;
1038 break;
1040 case 'x':
1041 c = *cptr++;
1042 n = hexval(c);
1043 if (n < 0 || n >= 16)
1044 illegal_character(c_cptr);
1045 for (;;)
1047 c = *cptr;
1048 i = hexval(c);
1049 if (i < 0 || i >= 16)
1050 break;
1051 ++cptr;
1052 n = (n << 4) + i;
1053 if (n > MAXCHAR)
1054 illegal_character(c_cptr);
1056 c = n;
1057 break;
1059 case 'a':
1060 c = 7;
1061 break;
1062 case 'b':
1063 c = '\b';
1064 break;
1065 case 'f':
1066 c = '\f';
1067 break;
1068 case 'n':
1069 c = '\n';
1070 break;
1071 case 'r':
1072 c = '\r';
1073 break;
1074 case 't':
1075 c = '\t';
1076 break;
1077 case 'v':
1078 c = '\v';
1079 break;
1082 cachec(c);
1084 FREE(a.a_line);
1086 n = cinc;
1087 s = TMALLOC(char, n);
1088 NO_SPACE(s);
1090 for (i = 0; i < n; ++i)
1091 s[i] = cache[i];
1093 cinc = 0;
1094 if (n == 1)
1095 cachec('\'');
1096 else
1097 cachec('"');
1099 for (i = 0; i < n; ++i)
1101 c = UCH(s[i]);
1102 if (c == '\\' || c == cache[0])
1104 cachec('\\');
1105 cachec(c);
1107 else if (isprint(c))
1108 cachec(c);
1109 else
1111 cachec('\\');
1112 switch (c)
1114 case 7:
1115 cachec('a');
1116 break;
1117 case '\b':
1118 cachec('b');
1119 break;
1120 case '\f':
1121 cachec('f');
1122 break;
1123 case '\n':
1124 cachec('n');
1125 break;
1126 case '\r':
1127 cachec('r');
1128 break;
1129 case '\t':
1130 cachec('t');
1131 break;
1132 case '\v':
1133 cachec('v');
1134 break;
1135 default:
1136 cachec(((c >> 6) & 7) + '0');
1137 cachec(((c >> 3) & 7) + '0');
1138 cachec((c & 7) + '0');
1139 break;
1144 if (n == 1)
1145 cachec('\'');
1146 else
1147 cachec('"');
1149 cachec(NUL);
1150 bp = lookup(cache);
1151 bp->class = TERM;
1152 if (n == 1 && bp->value == UNDEFINED)
1153 bp->value = UCH(*s);
1154 FREE(s);
1156 return (bp);
1159 static int
1160 is_reserved(char *name)
1162 char *s;
1164 if (strcmp(name, ".") == 0 ||
1165 strcmp(name, "$accept") == 0 ||
1166 strcmp(name, "$end") == 0)
1167 return (1);
1169 if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2])))
1171 s = name + 3;
1172 while (isdigit(UCH(*s)))
1173 ++s;
1174 if (*s == NUL)
1175 return (1);
1178 return (0);
1181 static bucket *
1182 get_name(void)
1184 int c;
1186 cinc = 0;
1187 for (c = *cptr; IS_IDENT(c); c = *++cptr)
1188 cachec(c);
1189 cachec(NUL);
1191 if (is_reserved(cache))
1192 used_reserved(cache);
1194 return (lookup(cache));
1197 static Value_t
1198 get_number(void)
1200 int c;
1201 Value_t n;
1203 n = 0;
1204 for (c = *cptr; isdigit(c); c = *++cptr)
1205 n = (Value_t) (10 * n + (c - '0'));
1207 return (n);
1210 static char *
1211 cache_tag(char *tag, size_t len)
1213 int i;
1214 char *s;
1216 for (i = 0; i < ntags; ++i)
1218 if (strncmp(tag, tag_table[i], len) == 0 &&
1219 tag_table[i][len] == NUL)
1220 return (tag_table[i]);
1223 if (ntags >= tagmax)
1225 tagmax += 16;
1226 tag_table =
1227 (tag_table
1228 ? TREALLOC(char *, tag_table, tagmax)
1229 : TMALLOC(char *, tagmax));
1230 NO_SPACE(tag_table);
1233 s = TMALLOC(char, len + 1);
1234 NO_SPACE(s);
1236 strncpy(s, tag, len);
1237 s[len] = 0;
1238 tag_table[ntags++] = s;
1239 return s;
1242 static char *
1243 get_tag(void)
1245 int c;
1246 int t_lineno = lineno;
1247 char *t_line = dup_line();
1248 char *t_cptr = t_line + (cptr - line);
1250 ++cptr;
1251 c = nextc();
1252 if (c == EOF)
1253 unexpected_EOF();
1254 if (!isalpha(c) && c != '_' && c != '$')
1255 illegal_tag(t_lineno, t_line, t_cptr);
1257 cinc = 0;
1260 cachec(c);
1261 c = *++cptr;
1263 while (IS_IDENT(c));
1264 cachec(NUL);
1266 c = nextc();
1267 if (c == EOF)
1268 unexpected_EOF();
1269 if (c != '>')
1270 illegal_tag(t_lineno, t_line, t_cptr);
1271 ++cptr;
1273 FREE(t_line);
1274 havetags = 1;
1275 return cache_tag(cache, (size_t) cinc);
1278 #if defined(YYBTYACC)
1279 static char *
1280 scan_id(void)
1282 char *b = cptr;
1284 while (isalnum((unsigned char)*cptr) || *cptr == '_' || *cptr == '$')
1285 cptr++;
1286 return cache_tag(b, (size_t) (cptr - b));
1288 #endif
1290 static void
1291 declare_tokens(int assoc)
1293 int c;
1294 bucket *bp;
1295 Value_t value;
1296 char *tag = 0;
1298 if (assoc != TOKEN)
1299 ++prec;
1301 c = nextc();
1302 if (c == EOF)
1303 unexpected_EOF();
1304 if (c == '<')
1306 tag = get_tag();
1307 c = nextc();
1308 if (c == EOF)
1309 unexpected_EOF();
1312 for (;;)
1314 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1315 bp = get_name();
1316 else if (c == '\'' || c == '"')
1317 bp = get_literal();
1318 else
1319 return;
1321 if (bp == goal)
1322 tokenized_start(bp->name);
1323 bp->class = TERM;
1325 if (tag)
1327 if (bp->tag && tag != bp->tag)
1328 retyped_warning(bp->name);
1329 bp->tag = tag;
1332 if (assoc != TOKEN)
1334 if (bp->prec && prec != bp->prec)
1335 reprec_warning(bp->name);
1336 bp->assoc = (Assoc_t) assoc;
1337 bp->prec = prec;
1340 c = nextc();
1341 if (c == EOF)
1342 unexpected_EOF();
1344 if (isdigit(c))
1346 value = get_number();
1347 if (bp->value != UNDEFINED && value != bp->value)
1348 revalued_warning(bp->name);
1349 bp->value = value;
1350 c = nextc();
1351 if (c == EOF)
1352 unexpected_EOF();
1358 * %expect requires special handling
1359 * as it really isn't part of the yacc
1360 * grammar only a flag for yacc proper.
1362 static void
1363 declare_expect(int assoc)
1365 int c;
1367 if (assoc != EXPECT && assoc != EXPECT_RR)
1368 ++prec;
1371 * Stay away from nextc - doesn't
1372 * detect EOL and will read to EOF.
1374 c = *++cptr;
1375 if (c == EOF)
1376 unexpected_EOF();
1378 for (;;)
1380 if (isdigit(c))
1382 if (assoc == EXPECT)
1383 SRexpect = get_number();
1384 else
1385 RRexpect = get_number();
1386 break;
1389 * Looking for number before EOL.
1390 * Spaces, tabs, and numbers are ok,
1391 * words, punc., etc. are syntax errors.
1393 else if (c == '\n' || isalpha(c) || !isspace(c))
1395 syntax_error(lineno, line, cptr);
1397 else
1399 c = *++cptr;
1400 if (c == EOF)
1401 unexpected_EOF();
1406 #if defined(YYBTYACC)
1407 static void
1408 declare_argtypes(bucket *bp)
1410 char *tags[MAXARGS];
1411 int args = 0, c;
1413 if (bp->args >= 0)
1414 retyped_warning(bp->name);
1415 cptr++; /* skip open paren */
1416 for (;;)
1418 c = nextc();
1419 if (c == EOF)
1420 unexpected_EOF();
1421 if (c != '<')
1422 syntax_error(lineno, line, cptr);
1423 tags[args++] = get_tag();
1424 c = nextc();
1425 if (c == R_PAREN)
1426 break;
1427 if (c == EOF)
1428 unexpected_EOF();
1430 cptr++; /* skip close paren */
1431 bp->args = args;
1432 bp->argnames = TMALLOC(char *, args);
1433 NO_SPACE(bp->argnames);
1434 bp->argtags = CALLOC(sizeof(char *), args + 1);
1435 NO_SPACE(bp->argtags);
1436 while (--args >= 0)
1438 bp->argtags[args] = tags[args];
1439 bp->argnames[args] = NULL;
1442 #endif
1444 static void
1445 declare_types(void)
1447 int c;
1448 bucket *bp;
1449 char *tag = NULL;
1451 c = nextc();
1452 if (c == EOF)
1453 unexpected_EOF();
1454 if (c == '<')
1455 tag = get_tag();
1457 for (;;)
1459 c = nextc();
1460 if (c == EOF)
1461 unexpected_EOF();
1462 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1464 bp = get_name();
1465 #if defined(YYBTYACC)
1466 if (nextc() == L_PAREN)
1467 declare_argtypes(bp);
1468 else
1469 bp->args = 0;
1470 #endif
1472 else if (c == '\'' || c == '"')
1474 bp = get_literal();
1475 #if defined(YYBTYACC)
1476 bp->args = 0;
1477 #endif
1479 else
1480 return;
1482 if (tag)
1484 if (bp->tag && tag != bp->tag)
1485 retyped_warning(bp->name);
1486 bp->tag = tag;
1491 static void
1492 declare_start(void)
1494 int c;
1495 bucket *bp;
1497 c = nextc();
1498 if (c == EOF)
1499 unexpected_EOF();
1500 if (!isalpha(c) && c != '_' && c != '.' && c != '$')
1501 syntax_error(lineno, line, cptr);
1502 bp = get_name();
1503 if (bp->class == TERM)
1504 terminal_start(bp->name);
1505 if (goal && goal != bp)
1506 restarted_warning();
1507 goal = bp;
1510 static void
1511 read_declarations(void)
1513 int c, k;
1515 cache_size = 256;
1516 cache = TMALLOC(char, cache_size);
1517 NO_SPACE(cache);
1519 for (;;)
1521 c = nextc();
1522 if (c == EOF)
1523 unexpected_EOF();
1524 if (c != '%')
1525 syntax_error(lineno, line, cptr);
1526 switch (k = keyword())
1528 case MARK:
1529 return;
1531 case IDENT:
1532 copy_ident();
1533 break;
1535 case TEXT:
1536 copy_text();
1537 break;
1539 case UNION:
1540 copy_union();
1541 break;
1543 case TOKEN:
1544 case LEFT:
1545 case RIGHT:
1546 case NONASSOC:
1547 declare_tokens(k);
1548 break;
1550 case EXPECT:
1551 case EXPECT_RR:
1552 declare_expect(k);
1553 break;
1555 case TYPE:
1556 declare_types();
1557 break;
1559 case START:
1560 declare_start();
1561 break;
1563 case PURE_PARSER:
1564 pure_parser = 1;
1565 break;
1567 case PARSE_PARAM:
1568 case LEX_PARAM:
1569 copy_param(k);
1570 break;
1572 case TOKEN_TABLE:
1573 token_table = 1;
1574 break;
1576 case ERROR_VERBOSE:
1577 error_verbose = 1;
1578 break;
1580 #if defined(YYBTYACC)
1581 case LOCATIONS:
1582 locations = 1;
1583 break;
1585 case DESTRUCTOR:
1586 destructor = 1;
1587 copy_destructor();
1588 break;
1589 case INITIAL_ACTION:
1590 copy_initial_action();
1591 break;
1592 #endif
1594 case XXXDEBUG:
1595 /* XXX: FIXME */
1596 break;
1598 case POSIX_YACC:
1599 /* noop for bison compatibility. byacc is already designed to be posix
1600 * yacc compatible. */
1601 break;
1606 static void
1607 initialize_grammar(void)
1609 nitems = 4;
1610 maxitems = 300;
1612 pitem = TMALLOC(bucket *, maxitems);
1613 NO_SPACE(pitem);
1615 pitem[0] = 0;
1616 pitem[1] = 0;
1617 pitem[2] = 0;
1618 pitem[3] = 0;
1620 nrules = 3;
1621 maxrules = 100;
1623 plhs = TMALLOC(bucket *, maxrules);
1624 NO_SPACE(plhs);
1626 plhs[0] = 0;
1627 plhs[1] = 0;
1628 plhs[2] = 0;
1630 rprec = TMALLOC(Value_t, maxrules);
1631 NO_SPACE(rprec);
1633 rprec[0] = 0;
1634 rprec[1] = 0;
1635 rprec[2] = 0;
1637 rassoc = TMALLOC(Assoc_t, maxrules);
1638 NO_SPACE(rassoc);
1640 rassoc[0] = TOKEN;
1641 rassoc[1] = TOKEN;
1642 rassoc[2] = TOKEN;
1645 static void
1646 expand_items(void)
1648 maxitems += 300;
1649 pitem = TREALLOC(bucket *, pitem, maxitems);
1650 NO_SPACE(pitem);
1653 static void
1654 expand_rules(void)
1656 maxrules += 100;
1658 plhs = TREALLOC(bucket *, plhs, maxrules);
1659 NO_SPACE(plhs);
1661 rprec = TREALLOC(Value_t, rprec, maxrules);
1662 NO_SPACE(rprec);
1664 rassoc = TREALLOC(Assoc_t, rassoc, maxrules);
1665 NO_SPACE(rassoc);
1668 /* set immediately prior to where copy_args() could be called, and incremented by
1669 the various routines that will rescan the argument list as appropriate */
1670 static int rescan_lineno;
1671 #if defined(YYBTYACC)
1673 static char *
1674 copy_args(int *alen)
1676 struct mstring *s = msnew();
1677 int depth = 0, len = 1;
1678 char c, quote = 0;
1679 struct ainfo a;
1681 a.a_lineno = lineno;
1682 a.a_line = dup_line();
1683 a.a_cptr = a.a_line + (cptr - line - 1);
1685 while ((c = *cptr++) != R_PAREN || depth || quote)
1687 if (c == ',' && !quote && !depth)
1689 len++;
1690 mputc(s, 0);
1691 continue;
1693 mputc(s, c);
1694 if (c == '\n')
1696 get_line();
1697 if (!line)
1699 if (quote)
1700 unterminated_string(&a);
1701 else
1702 unterminated_arglist(&a);
1705 else if (quote)
1707 if (c == quote)
1708 quote = 0;
1709 else if (c == '\\')
1711 if (*cptr != '\n')
1712 mputc(s, *cptr++);
1715 else
1717 if (c == L_PAREN)
1718 depth++;
1719 else if (c == R_PAREN)
1720 depth--;
1721 else if (c == '\"' || c == '\'')
1722 quote = c;
1725 if (alen)
1726 *alen = len;
1727 FREE(a.a_line);
1728 return msdone(s);
1731 static char *
1732 parse_id(char *p, char **save)
1734 char *b;
1736 while (isspace((unsigned char)*p))
1737 if (*p++ == '\n')
1738 rescan_lineno++;
1739 if (!isalpha((unsigned char)*p) && *p != '_')
1740 return NULL;
1741 b = p;
1742 while (isalnum((unsigned char)*p) || *p == '_' || *p == '$')
1743 p++;
1744 if (save)
1746 *save = cache_tag(b, (size_t) (p - b));
1748 return p;
1751 static char *
1752 parse_int(char *p, int *save)
1754 int neg = 0, val = 0;
1756 while (isspace((unsigned char)*p))
1757 if (*p++ == '\n')
1758 rescan_lineno++;
1759 if (*p == '-')
1761 neg = 1;
1762 p++;
1764 if (!isdigit((unsigned char)*p))
1765 return NULL;
1766 while (isdigit((unsigned char)*p))
1767 val = val * 10 + *p++ - '0';
1768 if (neg)
1769 val = -val;
1770 if (save)
1771 *save = val;
1772 return p;
1775 static void
1776 parse_arginfo(bucket *a, char *args, int argslen)
1778 char *p = args, *tmp;
1779 int i, redec = 0;
1781 if (a->args > 0)
1783 if (a->args != argslen)
1784 arg_number_disagree_warning(rescan_lineno, a->name);
1785 redec = 1;
1787 else
1789 if ((a->args = argslen) == 0)
1790 return;
1791 a->argnames = TMALLOC(char *, argslen);
1792 NO_SPACE(a->argnames);
1793 a->argtags = TMALLOC(char *, argslen);
1794 NO_SPACE(a->argtags);
1796 if (!args)
1797 return;
1798 for (i = 0; i < argslen; i++)
1800 while (isspace((unsigned char)*p))
1801 if (*p++ == '\n')
1802 rescan_lineno++;
1803 if (*p++ != '$')
1804 bad_formals();
1805 while (isspace((unsigned char)*p))
1806 if (*p++ == '\n')
1807 rescan_lineno++;
1808 if (*p == '<')
1810 havetags = 1;
1811 if (!(p = parse_id(p + 1, &tmp)))
1812 bad_formals();
1813 while (isspace((unsigned char)*p))
1814 if (*p++ == '\n')
1815 rescan_lineno++;
1816 if (*p++ != '>')
1817 bad_formals();
1818 if (redec)
1820 if (a->argtags[i] != tmp)
1821 arg_type_disagree_warning(rescan_lineno, i + 1, a->name);
1823 else
1824 a->argtags[i] = tmp;
1826 else if (!redec)
1827 a->argtags[i] = NULL;
1828 if (!(p = parse_id(p, &a->argnames[i])))
1829 bad_formals();
1830 while (isspace((unsigned char)*p))
1831 if (*p++ == '\n')
1832 rescan_lineno++;
1833 if (*p++)
1834 bad_formals();
1836 free(args);
1839 static char *
1840 compile_arg(char **theptr, char *yyvaltag)
1842 char *p = *theptr;
1843 struct mstring *c = msnew();
1844 int i, j, n;
1845 Value_t *offsets = NULL, maxoffset;
1846 bucket **rhs;
1848 maxoffset = 0;
1849 n = 0;
1850 for (i = nitems - 1; pitem[i]; --i)
1852 n++;
1853 if (pitem[i]->class != ARGUMENT)
1854 maxoffset++;
1856 if (maxoffset > 0)
1858 offsets = TMALLOC(Value_t, maxoffset + 1);
1859 NO_SPACE(offsets);
1861 for (j = 0, i++; i < nitems; i++)
1862 if (pitem[i]->class != ARGUMENT)
1863 offsets[++j] = (Value_t) (i - nitems + 1);
1865 rhs = pitem + nitems - 1;
1867 if (yyvaltag)
1868 msprintf(c, "yyval.%s = ", yyvaltag);
1869 else
1870 msprintf(c, "yyval = ");
1871 while (*p)
1873 if (*p == '$')
1875 char *tag = NULL;
1876 if (*++p == '<')
1877 if (!(p = parse_id(++p, &tag)) || *p++ != '>')
1878 illegal_tag(rescan_lineno, NULL, NULL);
1879 if (isdigit((unsigned char)*p) || *p == '-')
1881 int val;
1882 if (!(p = parse_int(p, &val)))
1883 dollar_error(rescan_lineno, NULL, NULL);
1884 if (val <= 0)
1885 i = val - n;
1886 else if (val > maxoffset)
1888 dollar_warning(rescan_lineno, val);
1889 i = val - maxoffset;
1891 else if (maxoffset > 0)
1893 i = offsets[val];
1894 if (!tag && !(tag = rhs[i]->tag) && havetags)
1895 untyped_rhs(val, rhs[i]->name);
1897 msprintf(c, "yystack.l_mark[%d]", i);
1898 if (tag)
1899 msprintf(c, ".%s", tag);
1900 else if (havetags)
1901 unknown_rhs(val);
1903 else if (isalpha((unsigned char)*p) || *p == '_')
1905 char *arg;
1906 if (!(p = parse_id(p, &arg)))
1907 dollar_error(rescan_lineno, NULL, NULL);
1908 for (i = plhs[nrules]->args - 1; i >= 0; i--)
1909 if (arg == plhs[nrules]->argnames[i])
1910 break;
1911 if (i < 0)
1912 unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL);
1913 else if (!tag)
1914 tag = plhs[nrules]->argtags[i];
1915 msprintf(c, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1
1916 - n);
1917 if (tag)
1918 msprintf(c, ".%s", tag);
1919 else if (havetags)
1920 untyped_arg_warning(rescan_lineno, "$", arg);
1922 else
1923 dollar_error(rescan_lineno, NULL, NULL);
1925 else if (*p == '@')
1927 at_error(rescan_lineno, NULL, NULL);
1929 else
1931 if (*p == '\n')
1932 rescan_lineno++;
1933 mputc(c, *p++);
1936 *theptr = p;
1937 if (maxoffset > 0)
1938 FREE(offsets);
1939 return msdone(c);
1942 #define ARG_CACHE_SIZE 1024
1943 static struct arg_cache
1945 struct arg_cache *next;
1946 char *code;
1947 int rule;
1949 *arg_cache[ARG_CACHE_SIZE];
1951 static int
1952 lookup_arg_cache(char *code)
1954 struct arg_cache *entry;
1956 entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE];
1957 while (entry)
1959 if (!strnscmp(entry->code, code))
1960 return entry->rule;
1961 entry = entry->next;
1963 return -1;
1966 static void
1967 insert_arg_cache(char *code, int rule)
1969 struct arg_cache *entry = NEW(struct arg_cache);
1970 int i;
1972 NO_SPACE(entry);
1973 i = strnshash(code) % ARG_CACHE_SIZE;
1974 entry->code = code;
1975 entry->rule = rule;
1976 entry->next = arg_cache[i];
1977 arg_cache[i] = entry;
1980 static void
1981 clean_arg_cache(void)
1983 struct arg_cache *e, *t;
1984 int i;
1986 for (i = 0; i < ARG_CACHE_SIZE; i++)
1988 for (e = arg_cache[i]; (t = e); e = e->next, FREE(t))
1989 free(e->code);
1990 arg_cache[i] = NULL;
1993 #endif
1995 static void
1996 advance_to_start(void)
1998 int c;
1999 bucket *bp;
2000 char *s_cptr;
2001 int s_lineno;
2002 #if defined(YYBTYACC)
2003 char *args = NULL;
2004 int argslen = 0;
2005 #endif
2007 for (;;)
2009 c = nextc();
2010 if (c != '%')
2011 break;
2012 s_cptr = cptr;
2013 switch (keyword())
2015 case MARK:
2016 no_grammar();
2018 case TEXT:
2019 copy_text();
2020 break;
2022 case START:
2023 declare_start();
2024 break;
2026 default:
2027 syntax_error(lineno, line, s_cptr);
2031 c = nextc();
2032 if (!isalpha(c) && c != '_' && c != '.' && c != '_')
2033 syntax_error(lineno, line, cptr);
2034 bp = get_name();
2035 if (goal == 0)
2037 if (bp->class == TERM)
2038 terminal_start(bp->name);
2039 goal = bp;
2042 s_lineno = lineno;
2043 c = nextc();
2044 if (c == EOF)
2045 unexpected_EOF();
2046 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2047 #if defined(YYBTYACC)
2048 if (c == L_PAREN)
2050 ++cptr;
2051 args = copy_args(&argslen);
2052 NO_SPACE(args);
2053 c = nextc();
2055 #endif
2056 if (c != ':')
2057 syntax_error(lineno, line, cptr);
2058 start_rule(bp, s_lineno);
2059 #if defined(YYBTYACC)
2060 parse_arginfo(bp, args, argslen);
2061 #endif
2062 ++cptr;
2065 static void
2066 start_rule(bucket *bp, int s_lineno)
2068 if (bp->class == TERM)
2069 terminal_lhs(s_lineno);
2070 bp->class = NONTERM;
2071 if (!bp->index)
2072 bp->index = nrules;
2073 if (nrules >= maxrules)
2074 expand_rules();
2075 plhs[nrules] = bp;
2076 rprec[nrules] = UNDEFINED;
2077 rassoc[nrules] = TOKEN;
2080 static void
2081 end_rule(void)
2083 int i;
2085 if (!last_was_action && plhs[nrules]->tag)
2087 if (pitem[nitems - 1])
2089 for (i = nitems - 1; (i > 0) && pitem[i]; --i)
2090 continue;
2091 if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag)
2092 default_action_warning();
2094 else
2096 default_action_warning();
2100 last_was_action = 0;
2101 if (nitems >= maxitems)
2102 expand_items();
2103 pitem[nitems] = 0;
2104 ++nitems;
2105 ++nrules;
2108 static void
2109 insert_empty_rule(void)
2111 bucket *bp, **bpp;
2113 assert(cache);
2114 sprintf(cache, "$$%d", ++gensym);
2115 bp = make_bucket(cache);
2116 last_symbol->next = bp;
2117 last_symbol = bp;
2118 bp->tag = plhs[nrules]->tag;
2119 bp->class = ACTION;
2120 #if defined(YYBTYACC)
2121 bp->args = 0;
2122 #endif
2124 nitems = (Value_t) (nitems + 2);
2125 if (nitems > maxitems)
2126 expand_items();
2127 bpp = pitem + nitems - 1;
2128 *bpp-- = bp;
2129 while ((bpp[0] = bpp[-1]) != 0)
2130 --bpp;
2132 if (++nrules >= maxrules)
2133 expand_rules();
2134 plhs[nrules] = plhs[nrules - 1];
2135 plhs[nrules - 1] = bp;
2136 rprec[nrules] = rprec[nrules - 1];
2137 rprec[nrules - 1] = 0;
2138 rassoc[nrules] = rassoc[nrules - 1];
2139 rassoc[nrules - 1] = TOKEN;
2142 #if defined(YYBTYACC)
2143 static char *
2144 insert_arg_rule(char *arg, char *tag)
2146 int line_number = rescan_lineno;
2147 char *code = compile_arg(&arg, tag);
2148 int rule = lookup_arg_cache(code);
2149 FILE *f = action_file;
2151 if (rule < 0)
2153 rule = nrules;
2154 insert_arg_cache(code, rule);
2155 fprintf(f, "case %d:\n", rule - 2);
2156 if (!lflag)
2157 fprintf(f, line_format, line_number, input_file_name);
2158 fprintf(f, "%s;\n", code);
2159 fprintf(f, "break;\n");
2160 insert_empty_rule();
2161 plhs[rule]->tag = tag;
2162 plhs[rule]->class = ARGUMENT;
2164 else
2166 if (++nitems > maxitems)
2167 expand_items();
2168 pitem[nitems - 1] = plhs[rule];
2169 free(code);
2171 return arg + 1;
2173 #endif
2175 static void
2176 add_symbol(void)
2178 int c;
2179 bucket *bp;
2180 int s_lineno = lineno;
2181 #if defined(YYBTYACC)
2182 char *args = NULL;
2183 int argslen = 0;
2184 #endif
2186 c = *cptr;
2187 if (c == '\'' || c == '"')
2188 bp = get_literal();
2189 else
2190 bp = get_name();
2192 c = nextc();
2193 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2194 #if defined(YYBTYACC)
2195 if (c == L_PAREN)
2197 ++cptr;
2198 args = copy_args(&argslen);
2199 NO_SPACE(args);
2200 c = nextc();
2202 #endif
2203 if (c == ':')
2205 end_rule();
2206 start_rule(bp, s_lineno);
2207 #if defined(YYBTYACC)
2208 parse_arginfo(bp, args, argslen);
2209 #endif
2210 ++cptr;
2211 return;
2214 if (last_was_action)
2215 insert_empty_rule();
2216 last_was_action = 0;
2218 #if defined(YYBTYACC)
2219 if (bp->args < 0)
2220 bp->args = argslen;
2221 if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL)
2223 int i;
2224 if (plhs[nrules]->args != bp->args)
2225 wrong_number_args_warning("default ", bp->name);
2226 for (i = bp->args - 1; i >= 0; i--)
2227 if (plhs[nrules]->argtags[i] != bp->argtags[i])
2228 wrong_type_for_arg_warning(i + 1, bp->name);
2230 else if (bp->args != argslen)
2231 wrong_number_args_warning("", bp->name);
2232 if (bp->args > 0 && argslen > 0)
2234 char *ap;
2235 int i;
2236 for (ap = args, i = 0; i < argslen; i++)
2237 ap = insert_arg_rule(ap, bp->argtags[i]);
2238 free(args);
2240 #endif /* defined(YYBTYACC) */
2242 if (++nitems > maxitems)
2243 expand_items();
2244 pitem[nitems - 1] = bp;
2247 static void
2248 copy_action(void)
2250 int c;
2251 int i, j, n;
2252 int depth;
2253 #if defined(YYBTYACC)
2254 int trialaction = 0;
2255 int haveyyval = 0;
2256 #endif
2257 char *tag;
2258 FILE *f = action_file;
2259 struct ainfo a;
2260 Value_t *offsets = NULL, maxoffset;
2261 bucket **rhs;
2263 a.a_lineno = lineno;
2264 a.a_line = dup_line();
2265 a.a_cptr = a.a_line + (cptr - line);
2267 if (last_was_action)
2268 insert_empty_rule();
2269 last_was_action = 1;
2271 fprintf(f, "case %d:\n", nrules - 2);
2272 #if defined(YYBTYACC)
2273 if (backtrack)
2275 if (*cptr != L_BRAC)
2276 fprintf(f, " if (!yytrial)\n");
2277 else
2278 trialaction = 1;
2280 #endif
2281 if (!lflag)
2282 fprintf(f, line_format, lineno, input_file_name);
2283 if (*cptr == '=')
2284 ++cptr;
2286 /* avoid putting curly-braces in first column, to ease editing */
2287 if (*after_blanks(cptr) == L_CURL)
2289 putc('\t', f);
2290 cptr = after_blanks(cptr);
2293 maxoffset = 0;
2294 n = 0;
2295 for (i = nitems - 1; pitem[i]; --i)
2297 ++n;
2298 if (pitem[i]->class != ARGUMENT)
2299 maxoffset++;
2301 if (maxoffset > 0)
2303 offsets = TMALLOC(Value_t, maxoffset + 1);
2304 NO_SPACE(offsets);
2306 for (j = 0, i++; i < nitems; i++)
2308 if (pitem[i]->class != ARGUMENT)
2310 offsets[++j] = (Value_t) (i - nitems + 1);
2314 rhs = pitem + nitems - 1;
2316 depth = 0;
2317 loop:
2318 c = *cptr;
2319 if (c == '$')
2321 if (cptr[1] == '<')
2323 int d_lineno = lineno;
2324 char *d_line = dup_line();
2325 char *d_cptr = d_line + (cptr - line);
2327 ++cptr;
2328 tag = get_tag();
2329 c = *cptr;
2330 if (c == '$')
2332 fprintf(f, "yyval.%s", tag);
2333 ++cptr;
2334 FREE(d_line);
2335 goto loop;
2337 else if (isdigit(c))
2339 i = get_number();
2340 if (i == 0)
2341 fprintf(f, "yystack.l_mark[%d].%s", -n, tag);
2342 else if (i > maxoffset)
2344 dollar_warning(d_lineno, i);
2345 fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag);
2347 else if (offsets)
2348 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2349 FREE(d_line);
2350 goto loop;
2352 else if (c == '-' && isdigit(UCH(cptr[1])))
2354 ++cptr;
2355 i = -get_number() - n;
2356 fprintf(f, "yystack.l_mark[%d].%s", i, tag);
2357 FREE(d_line);
2358 goto loop;
2360 #if defined(YYBTYACC)
2361 else if (isalpha(c) || c == '_')
2363 char *arg = scan_id();
2364 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2365 if (arg == plhs[nrules]->argnames[i])
2366 break;
2367 if (i < 0)
2368 unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr);
2369 fprintf(f, "yystack.l_mark[%d].%s", i - plhs[nrules]->args +
2370 1 - n, tag);
2371 FREE(d_line);
2372 goto loop;
2374 #endif
2375 else
2376 dollar_error(d_lineno, d_line, d_cptr);
2378 else if (cptr[1] == '$')
2380 if (havetags)
2382 tag = plhs[nrules]->tag;
2383 if (tag == 0)
2384 untyped_lhs();
2385 fprintf(f, "yyval.%s", tag);
2387 else
2388 fprintf(f, "yyval");
2389 cptr += 2;
2390 #if defined(YYBTYACC)
2391 haveyyval = 1;
2392 #endif
2393 goto loop;
2395 else if (isdigit(UCH(cptr[1])))
2397 ++cptr;
2398 i = get_number();
2399 if (havetags && offsets)
2401 if (i <= 0 || i > maxoffset)
2402 unknown_rhs(i);
2403 tag = rhs[offsets[i]]->tag;
2404 if (tag == 0)
2405 untyped_rhs(i, rhs[offsets[i]]->name);
2406 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2408 else
2410 if (i == 0)
2411 fprintf(f, "yystack.l_mark[%d]", -n);
2412 else if (i > maxoffset)
2414 dollar_warning(lineno, i);
2415 fprintf(f, "yystack.l_mark[%d]", i - maxoffset);
2417 else if (offsets)
2418 fprintf(f, "yystack.l_mark[%d]", offsets[i]);
2420 goto loop;
2422 else if (cptr[1] == '-')
2424 cptr += 2;
2425 i = get_number();
2426 if (havetags)
2427 unknown_rhs(-i);
2428 fprintf(f, "yystack.l_mark[%d]", -i - n);
2429 goto loop;
2431 #if defined(YYBTYACC)
2432 else if (isalpha((unsigned char)cptr[1]) || cptr[1] == '_')
2434 char *arg;
2435 ++cptr;
2436 arg = scan_id();
2437 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2438 if (arg == plhs[nrules]->argnames[i])
2439 break;
2440 if (i < 0)
2441 unknown_arg_warning(lineno, "$", arg, line, cptr);
2442 tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]);
2443 fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n);
2444 if (tag)
2445 fprintf(f, ".%s", tag);
2446 else if (havetags)
2447 untyped_arg_warning(lineno, "$", arg);
2448 goto loop;
2450 #endif
2452 #if defined(YYBTYACC)
2453 if (c == '@')
2455 if (!locations)
2457 int l_lineno = lineno;
2458 char *l_line = dup_line();
2459 char *l_cptr = l_line + (cptr - line);
2460 syntax_error(l_lineno, l_line, l_cptr);
2462 if (cptr[1] == '$')
2464 fprintf(f, "yyloc");
2465 cptr += 2;
2466 goto loop;
2468 else if (isdigit(UCH(cptr[1])))
2470 ++cptr;
2471 i = get_number();
2472 if (i == 0)
2473 fprintf(f, "yystack.p_mark[%d]", -n);
2474 else if (i > maxoffset)
2476 at_warning(lineno, i);
2477 fprintf(f, "yystack.p_mark[%d]", i - maxoffset);
2479 else if (offsets)
2480 fprintf(f, "yystack.p_mark[%d]", offsets[i]);
2481 goto loop;
2484 #endif
2485 if (isalpha(c) || c == '_' || c == '$')
2489 putc(c, f);
2490 c = *++cptr;
2492 while (isalnum(c) || c == '_' || c == '$');
2493 goto loop;
2495 ++cptr;
2496 #if defined(YYBTYACC)
2497 if (backtrack)
2499 if (trialaction && c == L_BRAC && depth == 0)
2501 ++depth;
2502 putc(L_CURL, f);
2503 goto loop;
2505 if (trialaction && c == R_BRAC && depth == 1)
2507 --depth;
2508 putc(R_CURL, f);
2509 c = nextc();
2510 if (c == L_BRAC && !haveyyval)
2512 goto loop;
2514 if (c == L_CURL && !haveyyval)
2516 fprintf(f, " if (!yytrial)\n");
2517 if (!lflag)
2518 fprintf(f, line_format, lineno, input_file_name);
2519 trialaction = 0;
2520 goto loop;
2522 fprintf(f, "\nbreak;\n");
2523 FREE(a.a_line);
2524 if (maxoffset > 0)
2525 FREE(offsets);
2526 return;
2529 #endif
2530 putc(c, f);
2531 switch (c)
2533 case '\n':
2534 get_line();
2535 if (line)
2536 goto loop;
2537 unterminated_action(&a);
2539 case ';':
2540 if (depth > 0)
2541 goto loop;
2542 fprintf(f, "\nbreak;\n");
2543 free(a.a_line);
2544 if (maxoffset > 0)
2545 FREE(offsets);
2546 return;
2548 #if defined(YYBTYACC)
2549 case L_BRAC:
2550 if (backtrack)
2551 ++depth;
2552 goto loop;
2554 case R_BRAC:
2555 if (backtrack)
2556 --depth;
2557 goto loop;
2558 #endif
2560 case L_CURL:
2561 ++depth;
2562 goto loop;
2564 case R_CURL:
2565 if (--depth > 0)
2566 goto loop;
2567 #if defined(YYBTYACC)
2568 if (backtrack)
2570 c = nextc();
2571 if (c == L_BRAC && !haveyyval)
2573 trialaction = 1;
2574 goto loop;
2576 if (c == L_CURL && !haveyyval)
2578 fprintf(f, " if (!yytrial)\n");
2579 if (!lflag)
2580 fprintf(f, line_format, lineno, input_file_name);
2581 goto loop;
2584 #endif
2585 fprintf(f, "\nbreak;\n");
2586 free(a.a_line);
2587 if (maxoffset > 0)
2588 FREE(offsets);
2589 return;
2591 case '\'':
2592 case '"':
2594 char *s = copy_string(c);
2595 fputs(s, f);
2596 free(s);
2598 goto loop;
2600 case '/':
2602 char *s = copy_comment();
2603 fputs(s, f);
2604 free(s);
2606 goto loop;
2608 default:
2609 goto loop;
2613 #if defined(YYBTYACC)
2614 static char *
2615 get_code(struct ainfo *a, const char *loc)
2617 int c;
2618 int depth;
2619 char *tag;
2620 struct mstring *code_mstr = msnew();
2622 if (!lflag)
2623 msprintf(code_mstr, line_format, lineno, input_file_name);
2625 cptr = after_blanks(cptr);
2626 if (*cptr == L_CURL)
2627 /* avoid putting curly-braces in first column, to ease editing */
2628 mputc(code_mstr, '\t');
2629 else
2630 syntax_error(lineno, line, cptr);
2632 a->a_lineno = lineno;
2633 a->a_line = dup_line();
2634 a->a_cptr = a->a_line + (cptr - line);
2636 depth = 0;
2637 loop:
2638 c = *cptr;
2639 if (c == '$')
2641 if (cptr[1] == '<')
2643 int d_lineno = lineno;
2644 char *d_line = dup_line();
2645 char *d_cptr = d_line + (cptr - line);
2647 ++cptr;
2648 tag = get_tag();
2649 c = *cptr;
2650 if (c == '$')
2652 msprintf(code_mstr, "(*val).%s", tag);
2653 ++cptr;
2654 FREE(d_line);
2655 goto loop;
2657 else
2658 dollar_error(d_lineno, d_line, d_cptr);
2660 else if (cptr[1] == '$')
2662 /* process '$$' later; replacement is context dependent */
2663 msprintf(code_mstr, "$$");
2664 cptr += 2;
2665 goto loop;
2668 if (c == '@' && cptr[1] == '$')
2670 if (!locations)
2672 int l_lineno = lineno;
2673 char *l_line = dup_line();
2674 char *l_cptr = l_line + (cptr - line);
2675 syntax_error(l_lineno, l_line, l_cptr);
2677 msprintf(code_mstr, "%s", loc);
2678 cptr += 2;
2679 goto loop;
2681 if (isalpha(c) || c == '_' || c == '$')
2685 mputc(code_mstr, c);
2686 c = *++cptr;
2688 while (isalnum(c) || c == '_' || c == '$');
2689 goto loop;
2691 ++cptr;
2692 mputc(code_mstr, c);
2693 switch (c)
2695 case '\n':
2696 get_line();
2697 if (line)
2698 goto loop;
2699 unterminated_action(a);
2701 case L_CURL:
2702 ++depth;
2703 goto loop;
2705 case R_CURL:
2706 if (--depth > 0)
2707 goto loop;
2708 goto out;
2710 case '\'':
2711 case '"':
2713 char *s = copy_string(c);
2714 msprintf(code_mstr, "%s", s);
2715 free(s);
2717 goto loop;
2719 case '/':
2721 char *s = copy_comment();
2722 msprintf(code_mstr, "%s", s);
2723 free(s);
2725 goto loop;
2727 default:
2728 goto loop;
2730 out:
2731 return msdone(code_mstr);
2734 static void
2735 copy_initial_action(void)
2737 struct ainfo a;
2739 initial_action = get_code(&a, "yyloc");
2740 free(a.a_line);
2743 static void
2744 copy_destructor(void)
2746 char *code_text;
2747 int c;
2748 struct ainfo a;
2749 bucket *bp;
2751 code_text = get_code(&a, "(*loc)");
2753 for (;;)
2755 c = nextc();
2756 if (c == EOF)
2757 unexpected_EOF();
2758 if (c == '<')
2760 if (cptr[1] == '>')
2761 { /* "no semantic type" default destructor */
2762 cptr += 2;
2763 if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL)
2765 static char untyped_default[] = "<>";
2766 bp = make_bucket("untyped default");
2767 bp->tag = untyped_default;
2768 default_destructor[UNTYPED_DEFAULT] = bp;
2770 if (bp->destructor != NULL)
2771 destructor_redeclared_warning(&a);
2772 else
2773 /* replace "$$" with "(*val)" in destructor code */
2774 bp->destructor = process_destructor_XX(code_text, NULL);
2776 else if (cptr[1] == '*' && cptr[2] == '>')
2777 { /* "no per-symbol or per-type" default destructor */
2778 cptr += 3;
2779 if ((bp = default_destructor[TYPED_DEFAULT]) == NULL)
2781 static char typed_default[] = "<*>";
2782 bp = make_bucket("typed default");
2783 bp->tag = typed_default;
2784 default_destructor[TYPED_DEFAULT] = bp;
2786 if (bp->destructor != NULL)
2787 destructor_redeclared_warning(&a);
2788 else
2790 /* postpone re-processing destructor $$s until end of grammar spec */
2791 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2792 NO_SPACE(bp->destructor);
2793 strcpy(bp->destructor, code_text);
2796 else
2797 { /* "semantic type" default destructor */
2798 char *tag = get_tag();
2799 bp = lookup_type_destructor(tag);
2800 if (bp->destructor != NULL)
2801 destructor_redeclared_warning(&a);
2802 else
2803 /* replace "$$" with "(*val).tag" in destructor code */
2804 bp->destructor = process_destructor_XX(code_text, tag);
2807 else if (isalpha(c) || c == '_' || c == '.' || c == '$')
2808 { /* "symbol" destructor */
2809 bp = get_name();
2810 if (bp->destructor != NULL)
2811 destructor_redeclared_warning(&a);
2812 else
2814 /* postpone re-processing destructor $$s until end of grammar spec */
2815 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2816 NO_SPACE(bp->destructor);
2817 strcpy(bp->destructor, code_text);
2820 else
2821 break;
2823 free(a.a_line);
2824 free(code_text);
2827 static char *
2828 process_destructor_XX(char *code, char *tag)
2830 int c;
2831 int quote;
2832 int depth;
2833 struct mstring *new_code = msnew();
2834 char *codeptr = code;
2836 depth = 0;
2837 loop: /* step thru code */
2838 c = *codeptr;
2839 if (c == '$' && codeptr[1] == '$')
2841 codeptr += 2;
2842 if (tag == NULL)
2843 msprintf(new_code, "(*val)");
2844 else
2845 msprintf(new_code, "(*val).%s", tag);
2846 goto loop;
2848 if (isalpha(c) || c == '_' || c == '$')
2852 mputc(new_code, c);
2853 c = *++codeptr;
2855 while (isalnum(c) || c == '_' || c == '$');
2856 goto loop;
2858 ++codeptr;
2859 mputc(new_code, c);
2860 switch (c)
2862 case L_CURL:
2863 ++depth;
2864 goto loop;
2866 case R_CURL:
2867 if (--depth > 0)
2868 goto loop;
2869 return msdone(new_code);
2871 case '\'':
2872 case '"':
2873 quote = c;
2874 for (;;)
2876 c = *codeptr++;
2877 mputc(new_code, c);
2878 if (c == quote)
2879 goto loop;
2880 if (c == '\\')
2882 c = *codeptr++;
2883 mputc(new_code, c);
2887 case '/':
2888 c = *codeptr;
2889 if (c == '*')
2891 mputc(new_code, c);
2892 ++codeptr;
2893 for (;;)
2895 c = *codeptr++;
2896 mputc(new_code, c);
2897 if (c == '*' && *codeptr == '/')
2899 mputc(new_code, '/');
2900 ++codeptr;
2901 goto loop;
2905 goto loop;
2907 default:
2908 goto loop;
2911 #endif /* defined(YYBTYACC) */
2913 static int
2914 mark_symbol(void)
2916 int c;
2917 bucket *bp = NULL;
2919 c = cptr[1];
2920 if (c == '%' || c == '\\')
2922 cptr += 2;
2923 return (1);
2926 if (c == '=')
2927 cptr += 2;
2928 else if ((c == 'p' || c == 'P') &&
2929 ((c = cptr[2]) == 'r' || c == 'R') &&
2930 ((c = cptr[3]) == 'e' || c == 'E') &&
2931 ((c = cptr[4]) == 'c' || c == 'C') &&
2932 ((c = cptr[5], !IS_IDENT(c))))
2933 cptr += 5;
2934 else
2935 syntax_error(lineno, line, cptr);
2937 c = nextc();
2938 if (isalpha(c) || c == '_' || c == '.' || c == '$')
2939 bp = get_name();
2940 else if (c == '\'' || c == '"')
2941 bp = get_literal();
2942 else
2944 syntax_error(lineno, line, cptr);
2947 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
2948 prec_redeclared();
2950 rprec[nrules] = bp->prec;
2951 rassoc[nrules] = bp->assoc;
2952 return (0);
2955 static void
2956 read_grammar(void)
2958 int c;
2960 initialize_grammar();
2961 advance_to_start();
2963 for (;;)
2965 c = nextc();
2966 if (c == EOF)
2967 break;
2968 if (isalpha(c)
2969 || c == '_'
2970 || c == '.'
2971 || c == '$'
2972 || c == '\''
2973 || c == '"')
2974 add_symbol();
2975 #if defined(YYBTYACC)
2976 else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC))
2977 #else
2978 else if (c == L_CURL || c == '=')
2979 #endif
2980 copy_action();
2981 else if (c == '|')
2983 end_rule();
2984 start_rule(plhs[nrules - 1], 0);
2985 ++cptr;
2987 else if (c == '%')
2989 if (mark_symbol())
2990 break;
2992 else
2993 syntax_error(lineno, line, cptr);
2995 end_rule();
2996 #if defined(YYBTYACC)
2997 if (goal->args > 0)
2998 start_requires_args(goal->name);
2999 #endif
3002 static void
3003 free_tags(void)
3005 int i;
3007 if (tag_table == 0)
3008 return;
3010 for (i = 0; i < ntags; ++i)
3012 assert(tag_table[i]);
3013 FREE(tag_table[i]);
3015 FREE(tag_table);
3018 static void
3019 pack_names(void)
3021 bucket *bp;
3022 char *p, *s, *t;
3024 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
3025 for (bp = first_symbol; bp; bp = bp->next)
3026 name_pool_size += strlen(bp->name) + 1;
3028 name_pool = TMALLOC(char, name_pool_size);
3029 NO_SPACE(name_pool);
3031 strlcpy(name_pool, "$accept", name_pool_size);
3032 strlcpy(name_pool + 8, "$end", name_pool_size - 8);
3033 t = name_pool + 13;
3034 for (bp = first_symbol; bp; bp = bp->next)
3036 p = t;
3037 s = bp->name;
3038 while ((*t++ = *s++) != 0)
3039 continue;
3040 FREE(bp->name);
3041 bp->name = p;
3045 static void
3046 check_symbols(void)
3048 bucket *bp;
3050 if (goal->class == UNKNOWN)
3051 undefined_goal(goal->name);
3053 for (bp = first_symbol; bp; bp = bp->next)
3055 if (bp->class == UNKNOWN)
3057 undefined_symbol_warning(bp->name);
3058 bp->class = TERM;
3063 static void
3064 protect_string(char *src, char **des)
3066 unsigned len;
3067 char *s;
3068 char *d;
3070 *des = src;
3071 if (src)
3073 len = 1;
3074 s = src;
3075 while (*s)
3077 if ('\\' == *s || '"' == *s)
3078 len++;
3079 s++;
3080 len++;
3083 *des = d = TMALLOC(char, len);
3084 NO_SPACE(d);
3086 s = src;
3087 while (*s)
3089 if ('\\' == *s || '"' == *s)
3090 *d++ = '\\';
3091 *d++ = *s++;
3093 *d = '\0';
3097 static void
3098 pack_symbols(void)
3100 bucket *bp;
3101 bucket **v;
3102 Value_t i, j, k, n;
3103 #if defined(YYBTYACC)
3104 Value_t max_tok_pval;
3105 #endif
3107 nsyms = 2;
3108 ntokens = 1;
3109 for (bp = first_symbol; bp; bp = bp->next)
3111 ++nsyms;
3112 if (bp->class == TERM)
3113 ++ntokens;
3115 start_symbol = (Value_t) ntokens;
3116 nvars = (Value_t) (nsyms - ntokens);
3118 symbol_name = TMALLOC(char *, nsyms);
3119 NO_SPACE(symbol_name);
3121 symbol_value = TMALLOC(Value_t, nsyms);
3122 NO_SPACE(symbol_value);
3124 symbol_prec = TMALLOC(Value_t, nsyms);
3125 NO_SPACE(symbol_prec);
3127 symbol_assoc = TMALLOC(char, nsyms);
3128 NO_SPACE(symbol_assoc);
3130 #if defined(YYBTYACC)
3131 symbol_pval = TMALLOC(Value_t, nsyms);
3132 NO_SPACE(symbol_pval);
3134 if (destructor)
3136 symbol_destructor = CALLOC(sizeof(char *), nsyms);
3137 NO_SPACE(symbol_destructor);
3139 symbol_type_tag = CALLOC(sizeof(char *), nsyms);
3140 NO_SPACE(symbol_type_tag);
3142 #endif
3144 v = TMALLOC(bucket *, nsyms);
3145 NO_SPACE(v);
3147 v[0] = 0;
3148 v[start_symbol] = 0;
3150 i = 1;
3151 j = (Value_t) (start_symbol + 1);
3152 for (bp = first_symbol; bp; bp = bp->next)
3154 if (bp->class == TERM)
3155 v[i++] = bp;
3156 else
3157 v[j++] = bp;
3159 assert(i == ntokens && j == nsyms);
3161 for (i = 1; i < ntokens; ++i)
3162 v[i]->index = i;
3164 goal->index = (Index_t) (start_symbol + 1);
3165 k = (Value_t) (start_symbol + 2);
3166 while (++i < nsyms)
3167 if (v[i] != goal)
3169 v[i]->index = k;
3170 ++k;
3173 goal->value = 0;
3174 k = 1;
3175 for (i = (Value_t) (start_symbol + 1); i < nsyms; ++i)
3177 if (v[i] != goal)
3179 v[i]->value = k;
3180 ++k;
3184 k = 0;
3185 for (i = 1; i < ntokens; ++i)
3187 n = v[i]->value;
3188 if (n > 256)
3190 for (j = k++; j > 0 && symbol_value[j - 1] > n; --j)
3191 symbol_value[j] = symbol_value[j - 1];
3192 symbol_value[j] = n;
3196 assert(v[1] != 0);
3198 if (v[1]->value == UNDEFINED)
3199 v[1]->value = 256;
3201 j = 0;
3202 n = 257;
3203 for (i = 2; i < ntokens; ++i)
3205 if (v[i]->value == UNDEFINED)
3207 while (j < k && n == symbol_value[j])
3209 while (++j < k && n == symbol_value[j])
3210 continue;
3211 ++n;
3213 v[i]->value = n;
3214 ++n;
3218 symbol_name[0] = name_pool + 8;
3219 symbol_value[0] = 0;
3220 symbol_prec[0] = 0;
3221 symbol_assoc[0] = TOKEN;
3222 #if defined(YYBTYACC)
3223 symbol_pval[0] = 0;
3224 max_tok_pval = 0;
3225 #endif
3226 for (i = 1; i < ntokens; ++i)
3228 symbol_name[i] = v[i]->name;
3229 symbol_value[i] = v[i]->value;
3230 symbol_prec[i] = v[i]->prec;
3231 symbol_assoc[i] = v[i]->assoc;
3232 #if defined(YYBTYACC)
3233 symbol_pval[i] = v[i]->value;
3234 if (symbol_pval[i] > max_tok_pval)
3235 max_tok_pval = symbol_pval[i];
3236 if (destructor)
3238 symbol_destructor[i] = v[i]->destructor;
3239 symbol_type_tag[i] = v[i]->tag;
3241 #endif
3243 symbol_name[start_symbol] = name_pool;
3244 symbol_value[start_symbol] = -1;
3245 symbol_prec[start_symbol] = 0;
3246 symbol_assoc[start_symbol] = TOKEN;
3247 #if defined(YYBTYACC)
3248 symbol_pval[start_symbol] = (Value_t) (max_tok_pval + 1);
3249 #endif
3250 for (++i; i < nsyms; ++i)
3252 k = v[i]->index;
3253 symbol_name[k] = v[i]->name;
3254 symbol_value[k] = v[i]->value;
3255 symbol_prec[k] = v[i]->prec;
3256 symbol_assoc[k] = v[i]->assoc;
3257 #if defined(YYBTYACC)
3258 symbol_pval[k] = (Value_t) ((max_tok_pval + 1) + v[i]->value + 1);
3259 if (destructor)
3261 symbol_destructor[k] = v[i]->destructor;
3262 symbol_type_tag[k] = v[i]->tag;
3264 #endif
3267 if (gflag)
3269 symbol_pname = TMALLOC(char *, nsyms);
3270 NO_SPACE(symbol_pname);
3272 for (i = 0; i < nsyms; ++i)
3273 protect_string(symbol_name[i], &(symbol_pname[i]));
3276 FREE(v);
3279 static void
3280 pack_grammar(void)
3282 int i;
3283 Value_t j;
3284 Assoc_t assoc;
3285 Value_t prec2;
3287 ritem = TMALLOC(Value_t, nitems);
3288 NO_SPACE(ritem);
3290 rlhs = TMALLOC(Value_t, nrules);
3291 NO_SPACE(rlhs);
3293 rrhs = TMALLOC(Value_t, nrules + 1);
3294 NO_SPACE(rrhs);
3296 rprec = TREALLOC(Value_t, rprec, nrules);
3297 NO_SPACE(rprec);
3299 rassoc = TREALLOC(Assoc_t, rassoc, nrules);
3300 NO_SPACE(rassoc);
3302 ritem[0] = -1;
3303 ritem[1] = goal->index;
3304 ritem[2] = 0;
3305 ritem[3] = -2;
3306 rlhs[0] = 0;
3307 rlhs[1] = 0;
3308 rlhs[2] = start_symbol;
3309 rrhs[0] = 0;
3310 rrhs[1] = 0;
3311 rrhs[2] = 1;
3313 j = 4;
3314 for (i = 3; i < nrules; ++i)
3316 #if defined(YYBTYACC)
3317 if (plhs[i]->args > 0)
3319 if (plhs[i]->argnames)
3321 FREE(plhs[i]->argnames);
3322 plhs[i]->argnames = NULL;
3324 if (plhs[i]->argtags)
3326 FREE(plhs[i]->argtags);
3327 plhs[i]->argtags = NULL;
3330 #endif /* defined(YYBTYACC) */
3331 rlhs[i] = plhs[i]->index;
3332 rrhs[i] = j;
3333 assoc = TOKEN;
3334 prec2 = 0;
3335 while (pitem[j])
3337 ritem[j] = pitem[j]->index;
3338 if (pitem[j]->class == TERM)
3340 prec2 = pitem[j]->prec;
3341 assoc = pitem[j]->assoc;
3343 ++j;
3345 ritem[j] = (Value_t) - i;
3346 ++j;
3347 if (rprec[i] == UNDEFINED)
3349 rprec[i] = prec2;
3350 rassoc[i] = assoc;
3353 rrhs[i] = j;
3355 FREE(plhs);
3356 FREE(pitem);
3357 #if defined(YYBTYACC)
3358 clean_arg_cache();
3359 #endif
3362 static void
3363 print_grammar(void)
3365 int i, k;
3366 size_t j, spacing = 0;
3367 FILE *f = verbose_file;
3369 if (!vflag)
3370 return;
3372 k = 1;
3373 for (i = 2; i < nrules; ++i)
3375 if (rlhs[i] != rlhs[i - 1])
3377 if (i != 2)
3378 fprintf(f, "\n");
3379 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
3380 spacing = strlen(symbol_name[rlhs[i]]) + 1;
3382 else
3384 fprintf(f, "%4d ", i - 2);
3385 j = spacing;
3386 while (j-- != 0)
3387 putc(' ', f);
3388 putc('|', f);
3391 while (ritem[k] >= 0)
3393 fprintf(f, " %s", symbol_name[ritem[k]]);
3394 ++k;
3396 ++k;
3397 putc('\n', f);
3401 #if defined(YYBTYACC)
3402 static void
3403 finalize_destructors(void)
3405 int i;
3406 bucket *bp;
3407 char *tag;
3409 for (i = 2; i < nsyms; ++i)
3411 tag = symbol_type_tag[i];
3412 if (symbol_destructor[i] == NULL)
3414 if (tag == NULL)
3415 { /* use <> destructor, if there is one */
3416 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3418 symbol_destructor[i] = TMALLOC(char,
3419 strlen(bp->destructor) + 1);
3420 NO_SPACE(symbol_destructor[i]);
3421 strcpy(symbol_destructor[i], bp->destructor);
3424 else
3425 { /* use type destructor for this tag, if there is one */
3426 bp = lookup_type_destructor(tag);
3427 if (bp->destructor != NULL)
3429 symbol_destructor[i] = TMALLOC(char,
3430 strlen(bp->destructor) + 1);
3431 NO_SPACE(symbol_destructor[i]);
3432 strcpy(symbol_destructor[i], bp->destructor);
3434 else
3435 { /* use <*> destructor, if there is one */
3436 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3437 /* replace "$$" with "(*val).tag" in destructor code */
3438 symbol_destructor[i]
3439 = process_destructor_XX(bp->destructor, tag);
3443 else
3444 { /* replace "$$" with "(*val)[.tag]" in destructor code */
3445 symbol_destructor[i]
3446 = process_destructor_XX(symbol_destructor[i], tag);
3449 /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */
3450 DO_FREE(symbol_type_tag); /* no longer needed */
3451 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3453 FREE(bp->name);
3454 /* 'bp->tag' is a static value, don't free */
3455 FREE(bp->destructor);
3456 FREE(bp);
3458 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3460 FREE(bp->name);
3461 /* 'bp->tag' is a static value, don't free */
3462 FREE(bp->destructor);
3463 FREE(bp);
3465 if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL)
3467 bucket *p;
3468 for (; bp; bp = p)
3470 p = bp->link;
3471 FREE(bp->name);
3472 /* 'bp->tag' freed by 'free_tags()' */
3473 FREE(bp->destructor);
3474 FREE(bp);
3478 #endif /* defined(YYBTYACC) */
3480 void
3481 reader(void)
3483 write_section(code_file, banner);
3484 create_symbol_table();
3485 read_declarations();
3486 read_grammar();
3487 free_symbol_table();
3488 pack_names();
3489 check_symbols();
3490 pack_symbols();
3491 pack_grammar();
3492 free_symbols();
3493 print_grammar();
3494 #if defined(YYBTYACC)
3495 if (destructor)
3496 finalize_destructors();
3497 #endif
3498 free_tags();
3501 #ifdef NO_LEAKS
3502 static param *
3503 free_declarations(param * list)
3505 while (list != 0)
3507 param *next = list->next;
3508 free(list->type);
3509 free(list->name);
3510 free(list->type2);
3511 free(list);
3512 list = next;
3514 return list;
3517 void
3518 reader_leaks(void)
3520 lex_param = free_declarations(lex_param);
3521 parse_param = free_declarations(parse_param);
3523 DO_FREE(line);
3524 DO_FREE(rrhs);
3525 DO_FREE(rlhs);
3526 DO_FREE(rprec);
3527 DO_FREE(ritem);
3528 DO_FREE(rassoc);
3529 DO_FREE(cache);
3530 DO_FREE(name_pool);
3531 DO_FREE(symbol_name);
3532 DO_FREE(symbol_prec);
3533 DO_FREE(symbol_assoc);
3534 DO_FREE(symbol_value);
3535 #if defined(YYBTYACC)
3536 DO_FREE(symbol_pval);
3537 DO_FREE(symbol_destructor);
3538 DO_FREE(symbol_type_tag);
3539 #endif
3541 #endif