time: Use clock_gettime
[dragonfly.git] / contrib / byacc / reader.c
blobd0d7b1a36d48b359b884c3087327188172c468d3
1 /* $Id: reader.c,v 1.58 2014/10/06 22:15:08 tom Exp $ */
3 #include "defs.h"
5 /* The line size must be a positive integer. One hundred was chosen */
6 /* because few lines in Yacc input grammars exceed 100 characters. */
7 /* Note that if a line exceeds LINESIZE characters, the line buffer */
8 /* will be expanded to accomodate it. */
10 #define LINESIZE 100
12 #define L_CURL '{'
13 #define R_CURL '}'
14 #define L_PAREN '('
15 #define R_PAREN ')'
16 #define L_BRAC '['
17 #define R_BRAC ']'
19 /* the maximum number of arguments (inherited attributes) to a non-terminal */
20 /* this is a hard limit, but seems more than adequate */
21 #define MAXARGS 20
23 static void start_rule(bucket *bp, int s_lineno);
24 #if defined(YYBTYACC)
25 static void copy_destructor(void);
26 static char *process_destructor_XX(char *code, char *tag);
27 #endif
29 static char *cache;
30 static int cinc, cache_size;
32 int ntags;
33 static int tagmax, havetags;
34 static char **tag_table;
36 static char saw_eof;
37 char unionized;
38 char *cptr, *line;
39 static int linesize;
41 static bucket *goal;
42 static Value_t prec;
43 static int gensym;
44 static char last_was_action;
46 static int maxitems;
47 static bucket **pitem;
49 static int maxrules;
50 static bucket **plhs;
52 static size_t name_pool_size;
53 static char *name_pool;
55 char line_format[] = "#line %d \"%s\"\n";
57 param *lex_param;
58 param *parse_param;
60 #if defined(YYBTYACC)
61 int destructor = 0; /* =1 if at least one %destructor */
63 static bucket *default_destructor[3] =
64 {0, 0, 0};
66 #define UNTYPED_DEFAULT 0
67 #define TYPED_DEFAULT 1
68 #define TYPE_SPECIFIED 2
70 static bucket *
71 lookup_type_destructor(char *tag)
73 const char fmt[] = "%.*s destructor";
74 char name[1024] = "\0";
75 bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED];
77 while ((bp = *bpp) != NULL)
79 if (bp->tag == tag)
80 return (bp);
81 bpp = &bp->link;
84 sprintf(name, fmt, (int)(sizeof(name) - sizeof(fmt)), tag);
85 *bpp = bp = make_bucket(name);
86 bp->tag = tag;
88 return (bp);
90 #endif /* defined(YYBTYACC) */
92 static void
93 cachec(int c)
95 assert(cinc >= 0);
96 if (cinc >= cache_size)
98 cache_size += 256;
99 cache = TREALLOC(char, cache, cache_size);
100 NO_SPACE(cache);
102 cache[cinc] = (char)c;
103 ++cinc;
106 static void
107 get_line(void)
109 FILE *f = input_file;
110 int c;
111 int i;
113 if (saw_eof || (c = getc(f)) == EOF)
115 if (line)
117 FREE(line);
118 line = 0;
120 cptr = 0;
121 saw_eof = 1;
122 return;
125 if (line == 0 || linesize != (LINESIZE + 1))
127 if (line)
128 FREE(line);
129 linesize = LINESIZE + 1;
130 line = TMALLOC(char, linesize);
131 NO_SPACE(line);
134 i = 0;
135 ++lineno;
136 for (;;)
138 line[i++] = (char)c;
139 if (c == '\n')
140 break;
141 if ((i + 3) >= linesize)
143 linesize += LINESIZE;
144 line = TREALLOC(char, line, linesize);
145 NO_SPACE(line);
147 c = getc(f);
148 if (c == EOF)
150 line[i++] = '\n';
151 saw_eof = 1;
152 break;
155 line[i] = '\0';
156 cptr = line;
157 return;
160 static char *
161 dup_line(void)
163 char *p, *s, *t;
165 if (line == 0)
166 return (0);
167 s = line;
168 while (*s != '\n')
169 ++s;
170 p = TMALLOC(char, s - line + 1);
171 NO_SPACE(p);
173 s = line;
174 t = p;
175 while ((*t++ = *s++) != '\n')
176 continue;
177 return (p);
180 static void
181 skip_comment(void)
183 char *s;
185 int st_lineno = lineno;
186 char *st_line = dup_line();
187 char *st_cptr = st_line + (cptr - line);
189 s = cptr + 2;
190 for (;;)
192 if (*s == '*' && s[1] == '/')
194 cptr = s + 2;
195 FREE(st_line);
196 return;
198 if (*s == '\n')
200 get_line();
201 if (line == 0)
202 unterminated_comment(st_lineno, st_line, st_cptr);
203 s = cptr;
205 else
206 ++s;
210 static int
211 next_inline(void)
213 char *s;
215 if (line == 0)
217 get_line();
218 if (line == 0)
219 return (EOF);
222 s = cptr;
223 for (;;)
225 switch (*s)
227 case '/':
228 if (s[1] == '*')
230 cptr = s;
231 skip_comment();
232 s = cptr;
233 break;
235 else if (s[1] == '/')
237 get_line();
238 if (line == 0)
239 return (EOF);
240 s = cptr;
241 break;
243 /* FALLTHRU */
245 default:
246 cptr = s;
247 return (*s);
252 static int
253 nextc(void)
255 int ch;
256 int finish = 0;
260 switch (ch = next_inline())
262 case '\n':
263 get_line();
264 break;
265 case ' ':
266 case '\t':
267 case '\f':
268 case '\r':
269 case '\v':
270 case ',':
271 case ';':
272 ++cptr;
273 break;
274 case '\\':
275 ch = '%';
276 /* FALLTHRU */
277 default:
278 finish = 1;
279 break;
282 while (!finish);
284 return ch;
286 /* *INDENT-OFF* */
287 static struct keyword
289 char name[13];
290 int token;
292 keywords[] = {
293 { "binary", NONASSOC },
294 #if defined(YYBTYACC)
295 { "destructor", DESTRUCTOR },
296 #endif
297 { "expect", EXPECT },
298 { "expect-rr", EXPECT_RR },
299 { "ident", IDENT },
300 { "left", LEFT },
301 { "lex-param", LEX_PARAM },
302 #if defined(YYBTYACC)
303 { "locations", LOCATIONS },
304 #endif
305 { "nonassoc", NONASSOC },
306 { "parse-param", PARSE_PARAM },
307 { "pure-parser", PURE_PARSER },
308 { "right", RIGHT },
309 { "start", START },
310 { "term", TOKEN },
311 { "token", TOKEN },
312 { "token-table", TOKEN_TABLE },
313 { "type", TYPE },
314 { "union", UNION },
315 { "yacc", POSIX_YACC },
317 /* *INDENT-ON* */
319 static int
320 compare_keys(const void *a, const void *b)
322 const struct keyword *p = (const struct keyword *)a;
323 const struct keyword *q = (const struct keyword *)b;
324 return strcmp(p->name, q->name);
327 static int
328 keyword(void)
330 int c;
331 char *t_cptr = cptr;
332 struct keyword *key;
334 c = *++cptr;
335 if (isalpha(c))
337 cinc = 0;
338 for (;;)
340 if (isalpha(c))
342 if (isupper(c))
343 c = tolower(c);
344 cachec(c);
346 else if (isdigit(c)
347 || c == '-'
348 || c == '.'
349 || c == '$')
351 cachec(c);
353 else if (c == '_')
355 /* treat keywords spelled with '_' as if it were '-' */
356 cachec('-');
358 else
360 break;
362 c = *++cptr;
364 cachec(NUL);
366 if ((key = bsearch(cache, keywords,
367 sizeof(keywords) / sizeof(*key),
368 sizeof(*key), compare_keys)))
369 return key->token;
371 else
373 ++cptr;
374 if (c == L_CURL)
375 return (TEXT);
376 if (c == '%' || c == '\\')
377 return (MARK);
378 if (c == '<')
379 return (LEFT);
380 if (c == '>')
381 return (RIGHT);
382 if (c == '0')
383 return (TOKEN);
384 if (c == '2')
385 return (NONASSOC);
387 syntax_error(lineno, line, t_cptr);
390 static void
391 copy_ident(void)
393 int c;
394 FILE *f = output_file;
396 c = nextc();
397 if (c == EOF)
398 unexpected_EOF();
399 if (c != '"')
400 syntax_error(lineno, line, cptr);
401 ++outline;
402 fprintf(f, "#ident \"");
403 for (;;)
405 c = *++cptr;
406 if (c == '\n')
408 fprintf(f, "\"\n");
409 return;
411 putc(c, f);
412 if (c == '"')
414 putc('\n', f);
415 ++cptr;
416 return;
421 static char *
422 copy_string(int quote)
424 struct mstring *temp = msnew();
425 int c;
426 int s_lineno = lineno;
427 char *s_line = dup_line();
428 char *s_cptr = s_line + (cptr - line - 1);
430 for (;;)
432 c = *cptr++;
433 mputc(temp, c);
434 if (c == quote)
436 FREE(s_line);
437 return msdone(temp);
439 if (c == '\n')
440 unterminated_string(s_lineno, s_line, s_cptr);
441 if (c == '\\')
443 c = *cptr++;
444 mputc(temp, c);
445 if (c == '\n')
447 get_line();
448 if (line == 0)
449 unterminated_string(s_lineno, s_line, s_cptr);
455 static char *
456 copy_comment(void)
458 struct mstring *temp = msnew();
459 int c;
461 c = *cptr;
462 if (c == '/')
464 mputc(temp, '*');
465 while ((c = *++cptr) != '\n')
467 mputc(temp, c);
468 if (c == '*' && cptr[1] == '/')
469 mputc(temp, ' ');
471 mputc(temp, '*');
472 mputc(temp, '/');
474 else if (c == '*')
476 int c_lineno = lineno;
477 char *c_line = dup_line();
478 char *c_cptr = c_line + (cptr - line - 1);
480 mputc(temp, c);
481 ++cptr;
482 for (;;)
484 c = *cptr++;
485 mputc(temp, c);
486 if (c == '*' && *cptr == '/')
488 mputc(temp, '/');
489 ++cptr;
490 FREE(c_line);
491 return msdone(temp);
493 if (c == '\n')
495 get_line();
496 if (line == 0)
497 unterminated_comment(c_lineno, c_line, c_cptr);
501 return msdone(temp);
504 static void
505 copy_text(void)
507 int c;
508 FILE *f = text_file;
509 int need_newline = 0;
510 int t_lineno = lineno;
511 char *t_line = dup_line();
512 char *t_cptr = t_line + (cptr - line - 2);
514 if (*cptr == '\n')
516 get_line();
517 if (line == 0)
518 unterminated_text(t_lineno, t_line, t_cptr);
520 if (!lflag)
521 fprintf(f, line_format, lineno, input_file_name);
523 loop:
524 c = *cptr++;
525 switch (c)
527 case '\n':
528 putc('\n', f);
529 need_newline = 0;
530 get_line();
531 if (line)
532 goto loop;
533 unterminated_text(t_lineno, t_line, t_cptr);
535 case '\'':
536 case '"':
537 putc(c, f);
539 char *s = copy_string(c);
540 fputs(s, f);
541 free(s);
543 need_newline = 1;
544 goto loop;
546 case '/':
547 putc(c, f);
549 char *s = copy_comment();
550 fputs(s, f);
551 free(s);
553 need_newline = 1;
554 goto loop;
556 case '%':
557 case '\\':
558 if (*cptr == R_CURL)
560 if (need_newline)
561 putc('\n', f);
562 ++cptr;
563 FREE(t_line);
564 return;
566 /* FALLTHRU */
568 default:
569 putc(c, f);
570 need_newline = 1;
571 goto loop;
575 static void
576 puts_both(const char *s)
578 fputs(s, text_file);
579 if (dflag)
580 fputs(s, union_file);
583 static void
584 putc_both(int c)
586 putc(c, text_file);
587 if (dflag)
588 putc(c, union_file);
591 static void
592 copy_union(void)
594 int c;
595 int depth;
596 int u_lineno = lineno;
597 char *u_line = dup_line();
598 char *u_cptr = u_line + (cptr - line - 6);
600 if (unionized)
601 over_unionized(cptr - 6);
602 unionized = 1;
604 if (!lflag)
605 fprintf(text_file, line_format, lineno, input_file_name);
607 puts_both("#ifdef YYSTYPE\n");
608 puts_both("#undef YYSTYPE_IS_DECLARED\n");
609 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
610 puts_both("#endif\n");
611 puts_both("#ifndef YYSTYPE_IS_DECLARED\n");
612 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
613 puts_both("typedef union");
615 depth = 0;
616 loop:
617 c = *cptr++;
618 putc_both(c);
619 switch (c)
621 case '\n':
622 get_line();
623 if (line == 0)
624 unterminated_union(u_lineno, u_line, u_cptr);
625 goto loop;
627 case L_CURL:
628 ++depth;
629 goto loop;
631 case R_CURL:
632 if (--depth == 0)
634 puts_both(" YYSTYPE;\n");
635 puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n");
636 FREE(u_line);
637 return;
639 goto loop;
641 case '\'':
642 case '"':
644 char *s = copy_string(c);
645 puts_both(s);
646 free(s);
648 goto loop;
650 case '/':
652 char *s = copy_comment();
653 puts_both(s);
654 free(s);
656 goto loop;
658 default:
659 goto loop;
663 static char *
664 after_blanks(char *s)
666 while (*s != '\0' && isspace(UCH(*s)))
667 ++s;
668 return s;
672 * Trim leading/trailing blanks, and collapse multiple embedded blanks to a
673 * single space. Return index to last character in the buffer.
675 static int
676 trim_blanks(char *buffer)
678 if (*buffer != '\0')
680 char *d = buffer;
681 char *s = after_blanks(d);
683 while ((*d++ = *s++) != '\0')
688 --d;
689 while ((--d != buffer) && isspace(UCH(*d)))
690 *d = '\0';
692 for (s = d = buffer; (*d++ = *s++) != '\0';)
694 if (isspace(UCH(*s)))
696 *s = ' ';
697 while (isspace(UCH(*s)))
699 *s++ = ' ';
701 --s;
706 return (int)strlen(buffer) - 1;
710 * Scan forward in the current line-buffer looking for a right-curly bracket.
712 * Parameters begin with a left-curly bracket, and continue until there are no
713 * more interesting characters after the last right-curly bracket on the
714 * current line. Bison documents parameters as separated like this:
715 * {type param1} {type2 param2}
716 * but also accepts commas (although some versions of bison mishandle this)
717 * {type param1, type2 param2}
719 static int
720 more_curly(void)
722 char *save = cptr;
723 int result = 0;
724 int finish = 0;
727 switch (next_inline())
729 case 0:
730 case '\n':
731 finish = 1;
732 break;
733 case R_CURL:
734 finish = 1;
735 result = 1;
736 break;
738 ++cptr;
740 while (!finish);
741 cptr = save;
742 return result;
745 static void
746 save_param(int k, char *buffer, int name, int type2)
748 param *head, *p;
750 p = TMALLOC(param, 1);
751 NO_SPACE(p);
753 p->type2 = strdup(buffer + type2);
754 NO_SPACE(p->type2);
755 buffer[type2] = '\0';
756 (void)trim_blanks(p->type2);
758 p->name = strdup(buffer + name);
759 NO_SPACE(p->name);
760 buffer[name] = '\0';
761 (void)trim_blanks(p->name);
763 p->type = strdup(buffer);
764 NO_SPACE(p->type);
765 (void)trim_blanks(p->type);
767 if (k == LEX_PARAM)
768 head = lex_param;
769 else
770 head = parse_param;
772 if (head != NULL)
774 while (head->next)
775 head = head->next;
776 head->next = p;
778 else
780 if (k == LEX_PARAM)
781 lex_param = p;
782 else
783 parse_param = p;
785 p->next = NULL;
789 * Keep a linked list of parameters. This may be multi-line, if the trailing
790 * right-curly bracket is absent.
792 static void
793 copy_param(int k)
795 int c;
796 int name, type2;
797 int curly = 0;
798 char *buf = 0;
799 int i = -1;
800 size_t buf_size = 0;
801 int st_lineno = lineno;
802 char *comma;
806 int state = curly;
807 c = next_inline();
808 switch (c)
810 case EOF:
811 unexpected_EOF();
812 break;
813 case L_CURL:
814 if (curly == 1)
816 goto oops;
818 curly = 1;
819 st_lineno = lineno;
820 break;
821 case R_CURL:
822 if (curly != 1)
824 goto oops;
826 curly = 2;
827 break;
828 case '\n':
829 if (curly == 0)
831 goto oops;
833 break;
834 case '%':
835 if ((curly == 1) && (cptr == line))
837 lineno = st_lineno;
838 missing_brace();
840 /* FALLTHRU */
841 case '"':
842 case '\'':
843 goto oops;
844 default:
845 if (curly == 0 && !isspace(UCH(c)))
847 goto oops;
849 break;
851 if (buf == 0)
853 buf_size = (size_t) linesize;
854 buf = TMALLOC(char, buf_size);
856 else if (c == '\n')
858 get_line();
859 if (line == 0)
860 unexpected_EOF();
861 --cptr;
862 buf_size += (size_t) linesize;
863 buf = TREALLOC(char, buf, buf_size);
865 NO_SPACE(buf);
866 if (curly)
868 if ((state == 2) && (c == L_CURL))
870 buf[++i] = ',';
872 else if ((state == 2) && isspace(UCH(c)))
876 else if ((c != L_CURL) && (c != R_CURL))
878 buf[++i] = (char)c;
881 cptr++;
883 while (curly < 2 || more_curly());
885 if (i == 0)
887 if (curly == 1)
889 lineno = st_lineno;
890 missing_brace();
892 goto oops;
895 buf[i--] = '\0';
896 i = trim_blanks(buf);
898 comma = buf - 1;
901 char *parms = (comma + 1);
902 comma = strchr(parms, ',');
903 if (comma != 0)
904 *comma = '\0';
906 (void)trim_blanks(parms);
907 i = (int)strlen(parms) - 1;
908 if (i < 0)
910 goto oops;
913 if (parms[i] == ']')
915 int level = 1;
916 while (i >= 0 && level > 0 && parms[i] != '[')
918 if (parms[i] == ']')
919 ++level;
920 else if (parms[i] == '[')
921 --level;
922 i--;
924 if (i <= 0)
925 unexpected_EOF();
926 type2 = i--;
928 else
930 type2 = i + 1;
933 while (i > 0 && (isalnum(UCH(parms[i])) || UCH(parms[i]) == '_'))
934 i--;
936 if (!isspace(UCH(parms[i])) && parms[i] != '*')
937 goto oops;
939 name = i + 1;
941 save_param(k, parms, name, type2);
943 while (comma != 0);
944 FREE(buf);
945 return;
947 oops:
948 FREE(buf);
949 syntax_error(lineno, line, cptr);
952 static int
953 hexval(int c)
955 if (c >= '0' && c <= '9')
956 return (c - '0');
957 if (c >= 'A' && c <= 'F')
958 return (c - 'A' + 10);
959 if (c >= 'a' && c <= 'f')
960 return (c - 'a' + 10);
961 return (-1);
964 static bucket *
965 get_literal(void)
967 int c, quote;
968 int i;
969 int n;
970 char *s;
971 bucket *bp;
972 int s_lineno = lineno;
973 char *s_line = dup_line();
974 char *s_cptr = s_line + (cptr - line);
976 quote = *cptr++;
977 cinc = 0;
978 for (;;)
980 c = *cptr++;
981 if (c == quote)
982 break;
983 if (c == '\n')
984 unterminated_string(s_lineno, s_line, s_cptr);
985 if (c == '\\')
987 char *c_cptr = cptr - 1;
989 c = *cptr++;
990 switch (c)
992 case '\n':
993 get_line();
994 if (line == 0)
995 unterminated_string(s_lineno, s_line, s_cptr);
996 continue;
998 case '0':
999 case '1':
1000 case '2':
1001 case '3':
1002 case '4':
1003 case '5':
1004 case '6':
1005 case '7':
1006 n = c - '0';
1007 c = *cptr;
1008 if (IS_OCTAL(c))
1010 n = (n << 3) + (c - '0');
1011 c = *++cptr;
1012 if (IS_OCTAL(c))
1014 n = (n << 3) + (c - '0');
1015 ++cptr;
1018 if (n > MAXCHAR)
1019 illegal_character(c_cptr);
1020 c = n;
1021 break;
1023 case 'x':
1024 c = *cptr++;
1025 n = hexval(c);
1026 if (n < 0 || n >= 16)
1027 illegal_character(c_cptr);
1028 for (;;)
1030 c = *cptr;
1031 i = hexval(c);
1032 if (i < 0 || i >= 16)
1033 break;
1034 ++cptr;
1035 n = (n << 4) + i;
1036 if (n > MAXCHAR)
1037 illegal_character(c_cptr);
1039 c = n;
1040 break;
1042 case 'a':
1043 c = 7;
1044 break;
1045 case 'b':
1046 c = '\b';
1047 break;
1048 case 'f':
1049 c = '\f';
1050 break;
1051 case 'n':
1052 c = '\n';
1053 break;
1054 case 'r':
1055 c = '\r';
1056 break;
1057 case 't':
1058 c = '\t';
1059 break;
1060 case 'v':
1061 c = '\v';
1062 break;
1065 cachec(c);
1067 FREE(s_line);
1069 n = cinc;
1070 s = TMALLOC(char, n);
1071 NO_SPACE(s);
1073 for (i = 0; i < n; ++i)
1074 s[i] = cache[i];
1076 cinc = 0;
1077 if (n == 1)
1078 cachec('\'');
1079 else
1080 cachec('"');
1082 for (i = 0; i < n; ++i)
1084 c = UCH(s[i]);
1085 if (c == '\\' || c == cache[0])
1087 cachec('\\');
1088 cachec(c);
1090 else if (isprint(c))
1091 cachec(c);
1092 else
1094 cachec('\\');
1095 switch (c)
1097 case 7:
1098 cachec('a');
1099 break;
1100 case '\b':
1101 cachec('b');
1102 break;
1103 case '\f':
1104 cachec('f');
1105 break;
1106 case '\n':
1107 cachec('n');
1108 break;
1109 case '\r':
1110 cachec('r');
1111 break;
1112 case '\t':
1113 cachec('t');
1114 break;
1115 case '\v':
1116 cachec('v');
1117 break;
1118 default:
1119 cachec(((c >> 6) & 7) + '0');
1120 cachec(((c >> 3) & 7) + '0');
1121 cachec((c & 7) + '0');
1122 break;
1127 if (n == 1)
1128 cachec('\'');
1129 else
1130 cachec('"');
1132 cachec(NUL);
1133 bp = lookup(cache);
1134 bp->class = TERM;
1135 if (n == 1 && bp->value == UNDEFINED)
1136 bp->value = UCH(*s);
1137 FREE(s);
1139 return (bp);
1142 static int
1143 is_reserved(char *name)
1145 char *s;
1147 if (strcmp(name, ".") == 0 ||
1148 strcmp(name, "$accept") == 0 ||
1149 strcmp(name, "$end") == 0)
1150 return (1);
1152 if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2])))
1154 s = name + 3;
1155 while (isdigit(UCH(*s)))
1156 ++s;
1157 if (*s == NUL)
1158 return (1);
1161 return (0);
1164 static bucket *
1165 get_name(void)
1167 int c;
1169 cinc = 0;
1170 for (c = *cptr; IS_IDENT(c); c = *++cptr)
1171 cachec(c);
1172 cachec(NUL);
1174 if (is_reserved(cache))
1175 used_reserved(cache);
1177 return (lookup(cache));
1180 static Value_t
1181 get_number(void)
1183 int c;
1184 Value_t n;
1186 n = 0;
1187 for (c = *cptr; isdigit(c); c = *++cptr)
1188 n = (Value_t) (10 * n + (c - '0'));
1190 return (n);
1193 static char *
1194 cache_tag(char *tag, size_t len)
1196 int i;
1197 char *s;
1199 for (i = 0; i < ntags; ++i)
1201 if (strncmp(tag, tag_table[i], len) == 0 &&
1202 tag_table[i][len] == NUL)
1203 return (tag_table[i]);
1206 if (ntags >= tagmax)
1208 tagmax += 16;
1209 tag_table =
1210 (tag_table
1211 ? TREALLOC(char *, tag_table, tagmax)
1212 : TMALLOC(char *, tagmax));
1213 NO_SPACE(tag_table);
1216 s = TMALLOC(char, len + 1);
1217 NO_SPACE(s);
1219 strncpy(s, tag, len);
1220 s[len] = 0;
1221 tag_table[ntags++] = s;
1222 return s;
1225 static char *
1226 get_tag(void)
1228 int c;
1229 int t_lineno = lineno;
1230 char *t_line = dup_line();
1231 char *t_cptr = t_line + (cptr - line);
1233 ++cptr;
1234 c = nextc();
1235 if (c == EOF)
1236 unexpected_EOF();
1237 if (!isalpha(c) && c != '_' && c != '$')
1238 illegal_tag(t_lineno, t_line, t_cptr);
1240 cinc = 0;
1243 cachec(c);
1244 c = *++cptr;
1246 while (IS_IDENT(c));
1247 cachec(NUL);
1249 c = nextc();
1250 if (c == EOF)
1251 unexpected_EOF();
1252 if (c != '>')
1253 illegal_tag(t_lineno, t_line, t_cptr);
1254 ++cptr;
1256 FREE(t_line);
1257 havetags = 1;
1258 return cache_tag(cache, (size_t) cinc);
1261 #if defined(YYBTYACC)
1262 static char *
1263 scan_id(void)
1265 char *b = cptr;
1267 while (isalnum(*cptr) || *cptr == '_' || *cptr == '$')
1268 cptr++;
1269 return cache_tag(b, (size_t) (cptr - b));
1271 #endif
1273 static void
1274 declare_tokens(int assoc)
1276 int c;
1277 bucket *bp;
1278 Value_t value;
1279 char *tag = 0;
1281 if (assoc != TOKEN)
1282 ++prec;
1284 c = nextc();
1285 if (c == EOF)
1286 unexpected_EOF();
1287 if (c == '<')
1289 tag = get_tag();
1290 c = nextc();
1291 if (c == EOF)
1292 unexpected_EOF();
1295 for (;;)
1297 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1298 bp = get_name();
1299 else if (c == '\'' || c == '"')
1300 bp = get_literal();
1301 else
1302 return;
1304 if (bp == goal)
1305 tokenized_start(bp->name);
1306 bp->class = TERM;
1308 if (tag)
1310 if (bp->tag && tag != bp->tag)
1311 retyped_warning(bp->name);
1312 bp->tag = tag;
1315 if (assoc != TOKEN)
1317 if (bp->prec && prec != bp->prec)
1318 reprec_warning(bp->name);
1319 bp->assoc = (Assoc_t) assoc;
1320 bp->prec = prec;
1323 c = nextc();
1324 if (c == EOF)
1325 unexpected_EOF();
1327 if (isdigit(c))
1329 value = get_number();
1330 if (bp->value != UNDEFINED && value != bp->value)
1331 revalued_warning(bp->name);
1332 bp->value = value;
1333 c = nextc();
1334 if (c == EOF)
1335 unexpected_EOF();
1341 * %expect requires special handling
1342 * as it really isn't part of the yacc
1343 * grammar only a flag for yacc proper.
1345 static void
1346 declare_expect(int assoc)
1348 int c;
1350 if (assoc != EXPECT && assoc != EXPECT_RR)
1351 ++prec;
1354 * Stay away from nextc - doesn't
1355 * detect EOL and will read to EOF.
1357 c = *++cptr;
1358 if (c == EOF)
1359 unexpected_EOF();
1361 for (;;)
1363 if (isdigit(c))
1365 if (assoc == EXPECT)
1366 SRexpect = get_number();
1367 else
1368 RRexpect = get_number();
1369 break;
1372 * Looking for number before EOL.
1373 * Spaces, tabs, and numbers are ok,
1374 * words, punc., etc. are syntax errors.
1376 else if (c == '\n' || isalpha(c) || !isspace(c))
1378 syntax_error(lineno, line, cptr);
1380 else
1382 c = *++cptr;
1383 if (c == EOF)
1384 unexpected_EOF();
1389 #if defined(YYBTYACC)
1390 static void
1391 declare_argtypes(bucket *bp)
1393 char *tags[MAXARGS];
1394 int args = 0, c;
1396 if (bp->args >= 0)
1397 retyped_warning(bp->name);
1398 cptr++; /* skip open paren */
1399 for (;;)
1401 c = nextc();
1402 if (c == EOF)
1403 unexpected_EOF();
1404 if (c != '<')
1405 syntax_error(lineno, line, cptr);
1406 tags[args++] = get_tag();
1407 c = nextc();
1408 if (c == R_PAREN)
1409 break;
1410 if (c == EOF)
1411 unexpected_EOF();
1413 cptr++; /* skip close paren */
1414 bp->args = args;
1415 bp->argnames = TMALLOC(char *, args);
1416 NO_SPACE(bp->argnames);
1417 bp->argtags = CALLOC(sizeof(char *), args + 1);
1418 NO_SPACE(bp->argtags);
1419 while (--args >= 0)
1421 bp->argtags[args] = tags[args];
1422 bp->argnames[args] = NULL;
1425 #endif
1427 static void
1428 declare_types(void)
1430 int c;
1431 bucket *bp;
1432 char *tag = NULL;
1434 c = nextc();
1435 if (c == EOF)
1436 unexpected_EOF();
1437 if (c == '<')
1438 tag = get_tag();
1440 for (;;)
1442 c = nextc();
1443 if (c == EOF)
1444 unexpected_EOF();
1445 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1447 bp = get_name();
1448 #if defined(YYBTYACC)
1449 if (nextc() == L_PAREN)
1450 declare_argtypes(bp);
1451 else
1452 bp->args = 0;
1453 #endif
1455 else if (c == '\'' || c == '"')
1457 bp = get_literal();
1458 #if defined(YYBTYACC)
1459 bp->args = 0;
1460 #endif
1462 else
1463 return;
1465 if (tag)
1467 if (bp->tag && tag != bp->tag)
1468 retyped_warning(bp->name);
1469 bp->tag = tag;
1474 static void
1475 declare_start(void)
1477 int c;
1478 bucket *bp;
1480 c = nextc();
1481 if (c == EOF)
1482 unexpected_EOF();
1483 if (!isalpha(c) && c != '_' && c != '.' && c != '$')
1484 syntax_error(lineno, line, cptr);
1485 bp = get_name();
1486 if (bp->class == TERM)
1487 terminal_start(bp->name);
1488 if (goal && goal != bp)
1489 restarted_warning();
1490 goal = bp;
1493 static void
1494 read_declarations(void)
1496 int c, k;
1498 cache_size = 256;
1499 cache = TMALLOC(char, cache_size);
1500 NO_SPACE(cache);
1502 for (;;)
1504 c = nextc();
1505 if (c == EOF)
1506 unexpected_EOF();
1507 if (c != '%')
1508 syntax_error(lineno, line, cptr);
1509 switch (k = keyword())
1511 case MARK:
1512 return;
1514 case IDENT:
1515 copy_ident();
1516 break;
1518 case TEXT:
1519 copy_text();
1520 break;
1522 case UNION:
1523 copy_union();
1524 break;
1526 case TOKEN:
1527 case LEFT:
1528 case RIGHT:
1529 case NONASSOC:
1530 declare_tokens(k);
1531 break;
1533 case EXPECT:
1534 case EXPECT_RR:
1535 declare_expect(k);
1536 break;
1538 case TYPE:
1539 declare_types();
1540 break;
1542 case START:
1543 declare_start();
1544 break;
1546 case PURE_PARSER:
1547 pure_parser = 1;
1548 break;
1550 case PARSE_PARAM:
1551 case LEX_PARAM:
1552 copy_param(k);
1553 break;
1555 case TOKEN_TABLE:
1556 token_table = 1;
1557 break;
1559 #if defined(YYBTYACC)
1560 case LOCATIONS:
1561 locations = 1;
1562 break;
1564 case DESTRUCTOR:
1565 destructor = 1;
1566 copy_destructor();
1567 break;
1568 #endif
1570 case POSIX_YACC:
1571 /* noop for bison compatibility. byacc is already designed to be posix
1572 * yacc compatible. */
1573 break;
1578 static void
1579 initialize_grammar(void)
1581 nitems = 4;
1582 maxitems = 300;
1584 pitem = TMALLOC(bucket *, maxitems);
1585 NO_SPACE(pitem);
1587 pitem[0] = 0;
1588 pitem[1] = 0;
1589 pitem[2] = 0;
1590 pitem[3] = 0;
1592 nrules = 3;
1593 maxrules = 100;
1595 plhs = TMALLOC(bucket *, maxrules);
1596 NO_SPACE(plhs);
1598 plhs[0] = 0;
1599 plhs[1] = 0;
1600 plhs[2] = 0;
1602 rprec = TMALLOC(Value_t, maxrules);
1603 NO_SPACE(rprec);
1605 rprec[0] = 0;
1606 rprec[1] = 0;
1607 rprec[2] = 0;
1609 rassoc = TMALLOC(Assoc_t, maxrules);
1610 NO_SPACE(rassoc);
1612 rassoc[0] = TOKEN;
1613 rassoc[1] = TOKEN;
1614 rassoc[2] = TOKEN;
1617 static void
1618 expand_items(void)
1620 maxitems += 300;
1621 pitem = TREALLOC(bucket *, pitem, maxitems);
1622 NO_SPACE(pitem);
1625 static void
1626 expand_rules(void)
1628 maxrules += 100;
1630 plhs = TREALLOC(bucket *, plhs, maxrules);
1631 NO_SPACE(plhs);
1633 rprec = TREALLOC(Value_t, rprec, maxrules);
1634 NO_SPACE(rprec);
1636 rassoc = TREALLOC(Assoc_t, rassoc, maxrules);
1637 NO_SPACE(rassoc);
1640 /* set immediately prior to where copy_args() could be called, and incremented by
1641 the various routines that will rescan the argument list as appropriate */
1642 static int rescan_lineno;
1643 #if defined(YYBTYACC)
1645 static char *
1646 copy_args(int *alen)
1648 struct mstring *s = msnew();
1649 int depth = 0, len = 1;
1650 char c, quote = 0;
1651 int a_lineno = lineno;
1652 char *a_line = dup_line();
1653 char *a_cptr = a_line + (cptr - line - 1);
1655 while ((c = *cptr++) != R_PAREN || depth || quote)
1657 if (c == ',' && !quote && !depth)
1659 len++;
1660 mputc(s, 0);
1661 continue;
1663 mputc(s, c);
1664 if (c == '\n')
1666 get_line();
1667 if (!line)
1669 if (quote)
1670 unterminated_string(a_lineno, a_line, a_cptr);
1671 else
1672 unterminated_arglist(a_lineno, a_line, a_cptr);
1675 else if (quote)
1677 if (c == quote)
1678 quote = 0;
1679 else if (c == '\\')
1681 if (*cptr != '\n')
1682 mputc(s, *cptr++);
1685 else
1687 if (c == L_PAREN)
1688 depth++;
1689 else if (c == R_PAREN)
1690 depth--;
1691 else if (c == '\"' || c == '\'')
1692 quote = c;
1695 if (alen)
1696 *alen = len;
1697 FREE(a_line);
1698 return msdone(s);
1701 static char *
1702 parse_id(char *p, char **save)
1704 char *b;
1706 while (isspace(*p))
1707 if (*p++ == '\n')
1708 rescan_lineno++;
1709 if (!isalpha(*p) && *p != '_')
1710 return NULL;
1711 b = p;
1712 while (isalnum(*p) || *p == '_' || *p == '$')
1713 p++;
1714 if (save)
1716 *save = cache_tag(b, (size_t) (p - b));
1718 return p;
1721 static char *
1722 parse_int(char *p, int *save)
1724 int neg = 0, val = 0;
1726 while (isspace(*p))
1727 if (*p++ == '\n')
1728 rescan_lineno++;
1729 if (*p == '-')
1731 neg = 1;
1732 p++;
1734 if (!isdigit(*p))
1735 return NULL;
1736 while (isdigit(*p))
1737 val = val * 10 + *p++ - '0';
1738 if (neg)
1739 val = -val;
1740 if (save)
1741 *save = val;
1742 return p;
1745 static void
1746 parse_arginfo(bucket *a, char *args, int argslen)
1748 char *p = args, *tmp;
1749 int i, redec = 0;
1751 if (a->args > 0)
1753 if (a->args != argslen)
1754 arg_number_disagree_warning(rescan_lineno, a->name);
1755 redec = 1;
1757 else
1759 if ((a->args = argslen) == 0)
1760 return;
1761 a->argnames = TMALLOC(char *, argslen);
1762 NO_SPACE(a->argnames);
1763 a->argtags = TMALLOC(char *, argslen);
1764 NO_SPACE(a->argtags);
1766 if (!args)
1767 return;
1768 for (i = 0; i < argslen; i++)
1770 while (isspace(*p))
1771 if (*p++ == '\n')
1772 rescan_lineno++;
1773 if (*p++ != '$')
1774 bad_formals();
1775 while (isspace(*p))
1776 if (*p++ == '\n')
1777 rescan_lineno++;
1778 if (*p == '<')
1780 havetags = 1;
1781 if (!(p = parse_id(p + 1, &tmp)))
1782 bad_formals();
1783 while (isspace(*p))
1784 if (*p++ == '\n')
1785 rescan_lineno++;
1786 if (*p++ != '>')
1787 bad_formals();
1788 if (redec)
1790 if (a->argtags[i] != tmp)
1791 arg_type_disagree_warning(rescan_lineno, i + 1, a->name);
1793 else
1794 a->argtags[i] = tmp;
1796 else if (!redec)
1797 a->argtags[i] = NULL;
1798 if (!(p = parse_id(p, &a->argnames[i])))
1799 bad_formals();
1800 while (isspace(*p))
1801 if (*p++ == '\n')
1802 rescan_lineno++;
1803 if (*p++)
1804 bad_formals();
1806 free(args);
1809 static char *
1810 compile_arg(char **theptr, char *yyvaltag)
1812 char *p = *theptr;
1813 struct mstring *c = msnew();
1814 int i, j, n;
1815 Value_t *offsets = NULL, maxoffset;
1816 bucket **rhs;
1818 maxoffset = 0;
1819 n = 0;
1820 for (i = nitems - 1; pitem[i]; --i)
1822 n++;
1823 if (pitem[i]->class != ARGUMENT)
1824 maxoffset++;
1826 if (maxoffset > 0)
1828 offsets = TMALLOC(Value_t, maxoffset + 1);
1829 NO_SPACE(offsets);
1831 for (j = 0, i++; i < nitems; i++)
1832 if (pitem[i]->class != ARGUMENT)
1833 offsets[++j] = (Value_t) (i - nitems + 1);
1835 rhs = pitem + nitems - 1;
1837 if (yyvaltag)
1838 msprintf(c, "yyval.%s = ", yyvaltag);
1839 else
1840 msprintf(c, "yyval = ");
1841 while (*p)
1843 if (*p == '$')
1845 char *tag = NULL;
1846 if (*++p == '<')
1847 if (!(p = parse_id(++p, &tag)) || *p++ != '>')
1848 illegal_tag(rescan_lineno, NULL, NULL);
1849 if (isdigit(*p) || *p == '-')
1851 int val;
1852 if (!(p = parse_int(p, &val)))
1853 dollar_error(rescan_lineno, NULL, NULL);
1854 if (val <= 0)
1855 i = val - n;
1856 else if (val > maxoffset)
1858 dollar_warning(rescan_lineno, val);
1859 i = val - maxoffset;
1861 else if (maxoffset > 0)
1863 i = offsets[val];
1864 if (!tag && !(tag = rhs[i]->tag) && havetags)
1865 untyped_rhs(val, rhs[i]->name);
1867 msprintf(c, "yystack.l_mark[%d]", i);
1868 if (tag)
1869 msprintf(c, ".%s", tag);
1870 else if (havetags)
1871 unknown_rhs(val);
1873 else if (isalpha(*p) || *p == '_')
1875 char *arg;
1876 if (!(p = parse_id(p, &arg)))
1877 dollar_error(rescan_lineno, NULL, NULL);
1878 for (i = plhs[nrules]->args - 1; i >= 0; i--)
1879 if (arg == plhs[nrules]->argnames[i])
1880 break;
1881 if (i < 0)
1882 unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL);
1883 else if (!tag)
1884 tag = plhs[nrules]->argtags[i];
1885 msprintf(c, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1
1886 - n);
1887 if (tag)
1888 msprintf(c, ".%s", tag);
1889 else if (havetags)
1890 untyped_arg_warning(rescan_lineno, "$", arg);
1892 else
1893 dollar_error(rescan_lineno, NULL, NULL);
1895 else if (*p == '@')
1897 at_error(rescan_lineno, NULL, NULL);
1899 else
1901 if (*p == '\n')
1902 rescan_lineno++;
1903 mputc(c, *p++);
1906 *theptr = p;
1907 if (maxoffset > 0)
1908 FREE(offsets);
1909 return msdone(c);
1912 #define ARG_CACHE_SIZE 1024
1913 static struct arg_cache
1915 struct arg_cache *next;
1916 char *code;
1917 int rule;
1919 *arg_cache[ARG_CACHE_SIZE];
1921 static int
1922 lookup_arg_cache(char *code)
1924 struct arg_cache *entry;
1926 entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE];
1927 while (entry)
1929 if (!strnscmp(entry->code, code))
1930 return entry->rule;
1931 entry = entry->next;
1933 return -1;
1936 static void
1937 insert_arg_cache(char *code, int rule)
1939 struct arg_cache *entry = NEW(struct arg_cache);
1940 int i;
1942 NO_SPACE(entry);
1943 i = strnshash(code) % ARG_CACHE_SIZE;
1944 entry->code = code;
1945 entry->rule = rule;
1946 entry->next = arg_cache[i];
1947 arg_cache[i] = entry;
1950 static void
1951 clean_arg_cache(void)
1953 struct arg_cache *e, *t;
1954 int i;
1956 for (i = 0; i < ARG_CACHE_SIZE; i++)
1958 for (e = arg_cache[i]; (t = e); e = e->next, FREE(t))
1959 free(e->code);
1960 arg_cache[i] = NULL;
1963 #endif
1965 static void
1966 advance_to_start(void)
1968 int c;
1969 bucket *bp;
1970 char *s_cptr;
1971 int s_lineno;
1972 #if defined(YYBTYACC)
1973 char *args = NULL;
1974 int argslen = 0;
1975 #endif
1977 for (;;)
1979 c = nextc();
1980 if (c != '%')
1981 break;
1982 s_cptr = cptr;
1983 switch (keyword())
1985 case MARK:
1986 no_grammar();
1988 case TEXT:
1989 copy_text();
1990 break;
1992 case START:
1993 declare_start();
1994 break;
1996 default:
1997 syntax_error(lineno, line, s_cptr);
2001 c = nextc();
2002 if (!isalpha(c) && c != '_' && c != '.' && c != '_')
2003 syntax_error(lineno, line, cptr);
2004 bp = get_name();
2005 if (goal == 0)
2007 if (bp->class == TERM)
2008 terminal_start(bp->name);
2009 goal = bp;
2012 s_lineno = lineno;
2013 c = nextc();
2014 if (c == EOF)
2015 unexpected_EOF();
2016 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2017 #if defined(YYBTYACC)
2018 if (c == L_PAREN)
2020 ++cptr;
2021 args = copy_args(&argslen);
2022 NO_SPACE(args);
2023 c = nextc();
2025 #endif
2026 if (c != ':')
2027 syntax_error(lineno, line, cptr);
2028 start_rule(bp, s_lineno);
2029 #if defined(YYBTYACC)
2030 parse_arginfo(bp, args, argslen);
2031 #endif
2032 ++cptr;
2035 static void
2036 start_rule(bucket *bp, int s_lineno)
2038 if (bp->class == TERM)
2039 terminal_lhs(s_lineno);
2040 bp->class = NONTERM;
2041 if (!bp->index)
2042 bp->index = nrules;
2043 if (nrules >= maxrules)
2044 expand_rules();
2045 plhs[nrules] = bp;
2046 rprec[nrules] = UNDEFINED;
2047 rassoc[nrules] = TOKEN;
2050 static void
2051 end_rule(void)
2053 int i;
2055 if (!last_was_action && plhs[nrules]->tag)
2057 if (pitem[nitems - 1])
2059 for (i = nitems - 1; (i > 0) && pitem[i]; --i)
2060 continue;
2061 if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag)
2062 default_action_warning();
2064 else
2066 default_action_warning();
2070 last_was_action = 0;
2071 if (nitems >= maxitems)
2072 expand_items();
2073 pitem[nitems] = 0;
2074 ++nitems;
2075 ++nrules;
2078 static void
2079 insert_empty_rule(void)
2081 bucket *bp, **bpp;
2083 assert(cache);
2084 sprintf(cache, "$$%d", ++gensym);
2085 bp = make_bucket(cache);
2086 last_symbol->next = bp;
2087 last_symbol = bp;
2088 bp->tag = plhs[nrules]->tag;
2089 bp->class = ACTION;
2090 #if defined(YYBTYACC)
2091 bp->args = 0;
2092 #endif
2094 nitems = (Value_t) (nitems + 2);
2095 if (nitems > maxitems)
2096 expand_items();
2097 bpp = pitem + nitems - 1;
2098 *bpp-- = bp;
2099 while ((bpp[0] = bpp[-1]) != 0)
2100 --bpp;
2102 if (++nrules >= maxrules)
2103 expand_rules();
2104 plhs[nrules] = plhs[nrules - 1];
2105 plhs[nrules - 1] = bp;
2106 rprec[nrules] = rprec[nrules - 1];
2107 rprec[nrules - 1] = 0;
2108 rassoc[nrules] = rassoc[nrules - 1];
2109 rassoc[nrules - 1] = TOKEN;
2112 #if defined(YYBTYACC)
2113 static char *
2114 insert_arg_rule(char *arg, char *tag)
2116 int line_number = rescan_lineno;
2117 char *code = compile_arg(&arg, tag);
2118 int rule = lookup_arg_cache(code);
2119 FILE *f = action_file;
2121 if (rule < 0)
2123 rule = nrules;
2124 insert_arg_cache(code, rule);
2125 fprintf(f, "case %d:\n", rule - 2);
2126 if (!lflag)
2127 fprintf(f, line_format, line_number, input_file_name);
2128 fprintf(f, "%s;\n", code);
2129 fprintf(f, "break;\n");
2130 insert_empty_rule();
2131 plhs[rule]->tag = tag;
2132 plhs[rule]->class = ARGUMENT;
2134 else
2136 if (++nitems > maxitems)
2137 expand_items();
2138 pitem[nitems - 1] = plhs[rule];
2139 free(code);
2141 return arg + 1;
2143 #endif
2145 static void
2146 add_symbol(void)
2148 int c;
2149 bucket *bp;
2150 int s_lineno = lineno;
2151 #if defined(YYBTYACC)
2152 char *args = NULL;
2153 int argslen = 0;
2154 #endif
2156 c = *cptr;
2157 if (c == '\'' || c == '"')
2158 bp = get_literal();
2159 else
2160 bp = get_name();
2162 c = nextc();
2163 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2164 #if defined(YYBTYACC)
2165 if (c == L_PAREN)
2167 ++cptr;
2168 args = copy_args(&argslen);
2169 NO_SPACE(args);
2170 c = nextc();
2172 #endif
2173 if (c == ':')
2175 end_rule();
2176 start_rule(bp, s_lineno);
2177 #if defined(YYBTYACC)
2178 parse_arginfo(bp, args, argslen);
2179 #endif
2180 ++cptr;
2181 return;
2184 if (last_was_action)
2185 insert_empty_rule();
2186 last_was_action = 0;
2188 #if defined(YYBTYACC)
2189 if (bp->args < 0)
2190 bp->args = argslen;
2191 if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL)
2193 int i;
2194 if (plhs[nrules]->args != bp->args)
2195 wrong_number_args_warning("default ", bp->name);
2196 for (i = bp->args - 1; i >= 0; i--)
2197 if (plhs[nrules]->argtags[i] != bp->argtags[i])
2198 wrong_type_for_arg_warning(i + 1, bp->name);
2200 else if (bp->args != argslen)
2201 wrong_number_args_warning("", bp->name);
2202 if (bp->args > 0 && argslen > 0)
2204 char *ap;
2205 int i;
2206 for (ap = args, i = 0; i < argslen; i++)
2207 ap = insert_arg_rule(ap, bp->argtags[i]);
2208 free(args);
2210 #endif /* defined(YYBTYACC) */
2212 if (++nitems > maxitems)
2213 expand_items();
2214 pitem[nitems - 1] = bp;
2217 static void
2218 copy_action(void)
2220 int c;
2221 int i, j, n;
2222 int depth;
2223 #if defined(YYBTYACC)
2224 int trialaction = 0;
2225 int haveyyval = 0;
2226 #endif
2227 char *tag;
2228 FILE *f = action_file;
2229 int a_lineno = lineno;
2230 char *a_line = dup_line();
2231 char *a_cptr = a_line + (cptr - line);
2232 Value_t *offsets = NULL, maxoffset;
2233 bucket **rhs;
2235 if (last_was_action)
2236 insert_empty_rule();
2237 last_was_action = 1;
2239 fprintf(f, "case %d:\n", nrules - 2);
2240 #if defined(YYBTYACC)
2241 if (backtrack)
2243 if (*cptr != L_BRAC)
2244 fprintf(f, " if (!yytrial)\n");
2245 else
2246 trialaction = 1;
2248 #endif
2249 if (!lflag)
2250 fprintf(f, line_format, lineno, input_file_name);
2251 if (*cptr == '=')
2252 ++cptr;
2254 /* avoid putting curly-braces in first column, to ease editing */
2255 if (*after_blanks(cptr) == L_CURL)
2257 putc('\t', f);
2258 cptr = after_blanks(cptr);
2261 maxoffset = 0;
2262 n = 0;
2263 for (i = nitems - 1; pitem[i]; --i)
2265 ++n;
2266 if (pitem[i]->class != ARGUMENT)
2267 maxoffset++;
2269 if (maxoffset > 0)
2271 offsets = TMALLOC(Value_t, maxoffset + 1);
2272 NO_SPACE(offsets);
2274 for (j = 0, i++; i < nitems; i++)
2276 if (pitem[i]->class != ARGUMENT)
2278 offsets[++j] = (Value_t) (i - nitems + 1);
2282 rhs = pitem + nitems - 1;
2284 depth = 0;
2285 loop:
2286 c = *cptr;
2287 if (c == '$')
2289 if (cptr[1] == '<')
2291 int d_lineno = lineno;
2292 char *d_line = dup_line();
2293 char *d_cptr = d_line + (cptr - line);
2295 ++cptr;
2296 tag = get_tag();
2297 c = *cptr;
2298 if (c == '$')
2300 fprintf(f, "yyval.%s", tag);
2301 ++cptr;
2302 FREE(d_line);
2303 goto loop;
2305 else if (isdigit(c))
2307 i = get_number();
2308 if (i == 0)
2309 fprintf(f, "yystack.l_mark[%d].%s", -n, tag);
2310 else if (i > maxoffset)
2312 dollar_warning(d_lineno, i);
2313 fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag);
2315 else if (offsets)
2316 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2317 FREE(d_line);
2318 goto loop;
2320 else if (c == '-' && isdigit(UCH(cptr[1])))
2322 ++cptr;
2323 i = -get_number() - n;
2324 fprintf(f, "yystack.l_mark[%d].%s", i, tag);
2325 FREE(d_line);
2326 goto loop;
2328 #if defined(YYBTYACC)
2329 else if (isalpha(c) || c == '_')
2331 char *arg = scan_id();
2332 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2333 if (arg == plhs[nrules]->argnames[i])
2334 break;
2335 if (i < 0)
2336 unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr);
2337 fprintf(f, "yystack.l_mark[%d].%s", i - plhs[nrules]->args +
2338 1 - n, tag);
2339 FREE(d_line);
2340 goto loop;
2342 #endif
2343 else
2344 dollar_error(d_lineno, d_line, d_cptr);
2346 else if (cptr[1] == '$')
2348 if (havetags)
2350 tag = plhs[nrules]->tag;
2351 if (tag == 0)
2352 untyped_lhs();
2353 fprintf(f, "yyval.%s", tag);
2355 else
2356 fprintf(f, "yyval");
2357 cptr += 2;
2358 #if defined(YYBTYACC)
2359 haveyyval = 1;
2360 #endif
2361 goto loop;
2363 else if (isdigit(UCH(cptr[1])))
2365 ++cptr;
2366 i = get_number();
2367 if (havetags && offsets)
2369 if (i <= 0 || i > maxoffset)
2370 unknown_rhs(i);
2371 tag = rhs[offsets[i]]->tag;
2372 if (tag == 0)
2373 untyped_rhs(i, rhs[offsets[i]]->name);
2374 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2376 else
2378 if (i == 0)
2379 fprintf(f, "yystack.l_mark[%d]", -n);
2380 else if (i > maxoffset)
2382 dollar_warning(lineno, i);
2383 fprintf(f, "yystack.l_mark[%d]", i - maxoffset);
2385 else if (offsets)
2386 fprintf(f, "yystack.l_mark[%d]", offsets[i]);
2388 goto loop;
2390 else if (cptr[1] == '-')
2392 cptr += 2;
2393 i = get_number();
2394 if (havetags)
2395 unknown_rhs(-i);
2396 fprintf(f, "yystack.l_mark[%d]", -i - n);
2397 goto loop;
2399 #if defined(YYBTYACC)
2400 else if (isalpha(cptr[1]) || cptr[1] == '_')
2402 char *arg;
2403 ++cptr;
2404 arg = scan_id();
2405 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2406 if (arg == plhs[nrules]->argnames[i])
2407 break;
2408 if (i < 0)
2409 unknown_arg_warning(lineno, "$", arg, line, cptr);
2410 tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]);
2411 fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n);
2412 if (tag)
2413 fprintf(f, ".%s", tag);
2414 else if (havetags)
2415 untyped_arg_warning(lineno, "$", arg);
2416 goto loop;
2418 #endif
2420 #if defined(YYBTYACC)
2421 if (c == '@')
2423 if (!locations)
2425 int l_lineno = lineno;
2426 char *l_line = dup_line();
2427 char *l_cptr = l_line + (cptr - line);
2428 syntax_error(l_lineno, l_line, l_cptr);
2430 if (cptr[1] == '$')
2432 fprintf(f, "yyloc");
2433 cptr += 2;
2434 goto loop;
2436 else if (isdigit(UCH(cptr[1])))
2438 ++cptr;
2439 i = get_number();
2440 if (i == 0)
2441 fprintf(f, "yystack.p_mark[%d]", -n);
2442 else if (i > maxoffset)
2444 at_warning(lineno, i);
2445 fprintf(f, "yystack.p_mark[%d]", i - maxoffset);
2447 else if (offsets)
2448 fprintf(f, "yystack.p_mark[%d]", offsets[i]);
2449 goto loop;
2452 #endif
2453 if (isalpha(c) || c == '_' || c == '$')
2457 putc(c, f);
2458 c = *++cptr;
2460 while (isalnum(c) || c == '_' || c == '$');
2461 goto loop;
2463 ++cptr;
2464 #if defined(YYBTYACC)
2465 if (backtrack)
2467 if (trialaction && c == L_BRAC && depth == 0)
2469 ++depth;
2470 putc(L_CURL, f);
2471 goto loop;
2473 if (trialaction && c == R_BRAC && depth == 1)
2475 --depth;
2476 putc(R_CURL, f);
2477 c = nextc();
2478 if (c == L_BRAC && !haveyyval)
2480 goto loop;
2482 if (c == L_CURL && !haveyyval)
2484 fprintf(f, " if (!yytrial)\n");
2485 if (!lflag)
2486 fprintf(f, line_format, lineno, input_file_name);
2487 trialaction = 0;
2488 goto loop;
2490 fprintf(f, "\nbreak;\n");
2491 FREE(a_line);
2492 if (maxoffset > 0)
2493 FREE(offsets);
2494 return;
2497 #endif
2498 putc(c, f);
2499 switch (c)
2501 case '\n':
2502 get_line();
2503 if (line)
2504 goto loop;
2505 unterminated_action(a_lineno, a_line, a_cptr);
2507 case ';':
2508 if (depth > 0)
2509 goto loop;
2510 fprintf(f, "\nbreak;\n");
2511 free(a_line);
2512 if (maxoffset > 0)
2513 FREE(offsets);
2514 return;
2516 #if defined(YYBTYACC)
2517 case L_BRAC:
2518 if (backtrack)
2519 ++depth;
2520 goto loop;
2522 case R_BRAC:
2523 if (backtrack)
2524 --depth;
2525 goto loop;
2526 #endif
2528 case L_CURL:
2529 ++depth;
2530 goto loop;
2532 case R_CURL:
2533 if (--depth > 0)
2534 goto loop;
2535 #if defined(YYBTYACC)
2536 if (backtrack)
2538 c = nextc();
2539 if (c == L_BRAC && !haveyyval)
2541 trialaction = 1;
2542 goto loop;
2544 if (c == L_CURL && !haveyyval)
2546 fprintf(f, " if (!yytrial)\n");
2547 if (!lflag)
2548 fprintf(f, line_format, lineno, input_file_name);
2549 goto loop;
2552 #endif
2553 fprintf(f, "\nbreak;\n");
2554 free(a_line);
2555 if (maxoffset > 0)
2556 FREE(offsets);
2557 return;
2559 case '\'':
2560 case '"':
2562 char *s = copy_string(c);
2563 fputs(s, f);
2564 free(s);
2566 goto loop;
2568 case '/':
2570 char *s = copy_comment();
2571 fputs(s, f);
2572 free(s);
2574 goto loop;
2576 default:
2577 goto loop;
2581 #if defined(YYBTYACC)
2582 static void
2583 copy_destructor(void)
2585 int c;
2586 int depth;
2587 char *tag;
2588 bucket *bp;
2589 struct mstring *destructor_text = msnew();
2590 char *code_text;
2591 int a_lineno;
2592 char *a_line;
2593 char *a_cptr;
2595 if (!lflag)
2596 msprintf(destructor_text, line_format, lineno, input_file_name);
2598 cptr = after_blanks(cptr);
2599 if (*cptr == L_CURL)
2600 /* avoid putting curly-braces in first column, to ease editing */
2601 mputc(destructor_text, '\t');
2602 else
2603 syntax_error(lineno, line, cptr);
2605 a_lineno = lineno;
2606 a_line = dup_line();
2607 a_cptr = a_line + (cptr - line);
2609 depth = 0;
2610 loop:
2611 c = *cptr;
2612 if (c == '$')
2614 if (cptr[1] == '<')
2616 int d_lineno = lineno;
2617 char *d_line = dup_line();
2618 char *d_cptr = d_line + (cptr - line);
2620 ++cptr;
2621 tag = get_tag();
2622 c = *cptr;
2623 if (c == '$')
2625 msprintf(destructor_text, "(*val).%s", tag);
2626 ++cptr;
2627 FREE(d_line);
2628 goto loop;
2630 else
2631 dollar_error(d_lineno, d_line, d_cptr);
2633 else if (cptr[1] == '$')
2635 /* process '$$' later; replacement is context dependent */
2636 msprintf(destructor_text, "$$");
2637 cptr += 2;
2638 goto loop;
2641 if (c == '@' && cptr[1] == '$')
2643 if (!locations)
2645 int l_lineno = lineno;
2646 char *l_line = dup_line();
2647 char *l_cptr = l_line + (cptr - line);
2648 syntax_error(l_lineno, l_line, l_cptr);
2650 msprintf(destructor_text, "(*loc)");
2651 cptr += 2;
2652 goto loop;
2654 if (isalpha(c) || c == '_' || c == '$')
2658 mputc(destructor_text, c);
2659 c = *++cptr;
2661 while (isalnum(c) || c == '_' || c == '$');
2662 goto loop;
2664 ++cptr;
2665 mputc(destructor_text, c);
2666 switch (c)
2668 case '\n':
2669 get_line();
2670 if (line)
2671 goto loop;
2672 unterminated_action(a_lineno, a_line, a_cptr);
2674 case L_CURL:
2675 ++depth;
2676 goto loop;
2678 case R_CURL:
2679 if (--depth > 0)
2680 goto loop;
2681 goto process_symbols;
2683 case '\'':
2684 case '"':
2686 char *s = copy_string(c);
2687 msprintf(destructor_text, "%s", s);
2688 free(s);
2690 goto loop;
2692 case '/':
2694 char *s = copy_comment();
2695 msprintf(destructor_text, "%s", s);
2696 free(s);
2698 goto loop;
2700 default:
2701 goto loop;
2703 process_symbols:
2704 code_text = msdone(destructor_text);
2705 for (;;)
2707 c = nextc();
2708 if (c == EOF)
2709 unexpected_EOF();
2710 if (c == '<')
2712 if (cptr[1] == '>')
2713 { /* "no semantic type" default destructor */
2714 cptr += 2;
2715 if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL)
2717 static char untyped_default[] = "<>";
2718 bp = make_bucket("untyped default");
2719 bp->tag = untyped_default;
2720 default_destructor[UNTYPED_DEFAULT] = bp;
2722 if (bp->destructor != NULL)
2723 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2724 else
2725 /* replace "$$" with "(*val)" in destructor code */
2726 bp->destructor = process_destructor_XX(code_text, NULL);
2728 else if (cptr[1] == '*' && cptr[2] == '>')
2729 { /* "no per-symbol or per-type" default destructor */
2730 cptr += 3;
2731 if ((bp = default_destructor[TYPED_DEFAULT]) == NULL)
2733 static char typed_default[] = "<*>";
2734 bp = make_bucket("typed default");
2735 bp->tag = typed_default;
2736 default_destructor[TYPED_DEFAULT] = bp;
2738 if (bp->destructor != NULL)
2739 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2740 else
2742 /* postpone re-processing destructor $$s until end of grammar spec */
2743 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2744 NO_SPACE(bp->destructor);
2745 strcpy(bp->destructor, code_text);
2748 else
2749 { /* "semantic type" default destructor */
2750 tag = get_tag();
2751 bp = lookup_type_destructor(tag);
2752 if (bp->destructor != NULL)
2753 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2754 else
2755 /* replace "$$" with "(*val).tag" in destructor code */
2756 bp->destructor = process_destructor_XX(code_text, tag);
2759 else if (isalpha(c) || c == '_' || c == '.' || c == '$')
2760 { /* "symbol" destructor */
2761 bp = get_name();
2762 if (bp->destructor != NULL)
2763 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2764 else
2766 /* postpone re-processing destructor $$s until end of grammar spec */
2767 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2768 NO_SPACE(bp->destructor);
2769 strcpy(bp->destructor, code_text);
2772 else
2773 break;
2775 free(a_line);
2776 free(code_text);
2779 static char *
2780 process_destructor_XX(char *code, char *tag)
2782 int c;
2783 int quote;
2784 int depth;
2785 struct mstring *new_code = msnew();
2786 char *codeptr = code;
2788 depth = 0;
2789 loop: /* step thru code */
2790 c = *codeptr;
2791 if (c == '$' && codeptr[1] == '$')
2793 codeptr += 2;
2794 if (tag == NULL)
2795 msprintf(new_code, "(*val)");
2796 else
2797 msprintf(new_code, "(*val).%s", tag);
2798 goto loop;
2800 if (isalpha(c) || c == '_' || c == '$')
2804 mputc(new_code, c);
2805 c = *++codeptr;
2807 while (isalnum(c) || c == '_' || c == '$');
2808 goto loop;
2810 ++codeptr;
2811 mputc(new_code, c);
2812 switch (c)
2814 case L_CURL:
2815 ++depth;
2816 goto loop;
2818 case R_CURL:
2819 if (--depth > 0)
2820 goto loop;
2821 return msdone(new_code);
2823 case '\'':
2824 case '"':
2825 quote = c;
2826 for (;;)
2828 c = *codeptr++;
2829 mputc(new_code, c);
2830 if (c == quote)
2831 goto loop;
2832 if (c == '\\')
2834 c = *codeptr++;
2835 mputc(new_code, c);
2839 case '/':
2840 c = *codeptr;
2841 if (c == '*')
2843 mputc(new_code, c);
2844 ++codeptr;
2845 for (;;)
2847 c = *codeptr++;
2848 mputc(new_code, c);
2849 if (c == '*' && *codeptr == '/')
2851 mputc(new_code, '/');
2852 ++codeptr;
2853 goto loop;
2857 goto loop;
2859 default:
2860 goto loop;
2863 #endif /* defined(YYBTYACC) */
2865 static int
2866 mark_symbol(void)
2868 int c;
2869 bucket *bp = NULL;
2871 c = cptr[1];
2872 if (c == '%' || c == '\\')
2874 cptr += 2;
2875 return (1);
2878 if (c == '=')
2879 cptr += 2;
2880 else if ((c == 'p' || c == 'P') &&
2881 ((c = cptr[2]) == 'r' || c == 'R') &&
2882 ((c = cptr[3]) == 'e' || c == 'E') &&
2883 ((c = cptr[4]) == 'c' || c == 'C') &&
2884 ((c = cptr[5], !IS_IDENT(c))))
2885 cptr += 5;
2886 else
2887 syntax_error(lineno, line, cptr);
2889 c = nextc();
2890 if (isalpha(c) || c == '_' || c == '.' || c == '$')
2891 bp = get_name();
2892 else if (c == '\'' || c == '"')
2893 bp = get_literal();
2894 else
2896 syntax_error(lineno, line, cptr);
2899 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
2900 prec_redeclared();
2902 rprec[nrules] = bp->prec;
2903 rassoc[nrules] = bp->assoc;
2904 return (0);
2907 static void
2908 read_grammar(void)
2910 int c;
2912 initialize_grammar();
2913 advance_to_start();
2915 for (;;)
2917 c = nextc();
2918 if (c == EOF)
2919 break;
2920 if (isalpha(c)
2921 || c == '_'
2922 || c == '.'
2923 || c == '$'
2924 || c == '\''
2925 || c == '"')
2926 add_symbol();
2927 #if defined(YYBTYACC)
2928 else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC))
2929 #else
2930 else if (c == L_CURL || c == '=')
2931 #endif
2932 copy_action();
2933 else if (c == '|')
2935 end_rule();
2936 start_rule(plhs[nrules - 1], 0);
2937 ++cptr;
2939 else if (c == '%')
2941 if (mark_symbol())
2942 break;
2944 else
2945 syntax_error(lineno, line, cptr);
2947 end_rule();
2948 #if defined(YYBTYACC)
2949 if (goal->args > 0)
2950 start_requires_args(goal->name);
2951 #endif
2954 static void
2955 free_tags(void)
2957 int i;
2959 if (tag_table == 0)
2960 return;
2962 for (i = 0; i < ntags; ++i)
2964 assert(tag_table[i]);
2965 FREE(tag_table[i]);
2967 FREE(tag_table);
2970 static void
2971 pack_names(void)
2973 bucket *bp;
2974 char *p, *s, *t;
2976 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
2977 for (bp = first_symbol; bp; bp = bp->next)
2978 name_pool_size += strlen(bp->name) + 1;
2980 name_pool = TMALLOC(char, name_pool_size);
2981 NO_SPACE(name_pool);
2983 strcpy(name_pool, "$accept");
2984 strcpy(name_pool + 8, "$end");
2985 t = name_pool + 13;
2986 for (bp = first_symbol; bp; bp = bp->next)
2988 p = t;
2989 s = bp->name;
2990 while ((*t++ = *s++) != 0)
2991 continue;
2992 FREE(bp->name);
2993 bp->name = p;
2997 static void
2998 check_symbols(void)
3000 bucket *bp;
3002 if (goal->class == UNKNOWN)
3003 undefined_goal(goal->name);
3005 for (bp = first_symbol; bp; bp = bp->next)
3007 if (bp->class == UNKNOWN)
3009 undefined_symbol_warning(bp->name);
3010 bp->class = TERM;
3015 static void
3016 protect_string(char *src, char **des)
3018 unsigned len;
3019 char *s;
3020 char *d;
3022 *des = src;
3023 if (src)
3025 len = 1;
3026 s = src;
3027 while (*s)
3029 if ('\\' == *s || '"' == *s)
3030 len++;
3031 s++;
3032 len++;
3035 *des = d = TMALLOC(char, len);
3036 NO_SPACE(d);
3038 s = src;
3039 while (*s)
3041 if ('\\' == *s || '"' == *s)
3042 *d++ = '\\';
3043 *d++ = *s++;
3045 *d = '\0';
3049 static void
3050 pack_symbols(void)
3052 bucket *bp;
3053 bucket **v;
3054 Value_t i, j, k, n;
3055 #if defined(YYBTYACC)
3056 Value_t max_tok_pval;
3057 #endif
3059 nsyms = 2;
3060 ntokens = 1;
3061 for (bp = first_symbol; bp; bp = bp->next)
3063 ++nsyms;
3064 if (bp->class == TERM)
3065 ++ntokens;
3067 start_symbol = (Value_t) ntokens;
3068 nvars = (Value_t) (nsyms - ntokens);
3070 symbol_name = TMALLOC(char *, nsyms);
3071 NO_SPACE(symbol_name);
3073 symbol_value = TMALLOC(Value_t, nsyms);
3074 NO_SPACE(symbol_value);
3076 symbol_prec = TMALLOC(Value_t, nsyms);
3077 NO_SPACE(symbol_prec);
3079 symbol_assoc = TMALLOC(char, nsyms);
3080 NO_SPACE(symbol_assoc);
3082 #if defined(YYBTYACC)
3083 symbol_pval = TMALLOC(Value_t, nsyms);
3084 NO_SPACE(symbol_pval);
3086 if (destructor)
3088 symbol_destructor = CALLOC(sizeof(char *), nsyms);
3089 NO_SPACE(symbol_destructor);
3091 symbol_type_tag = CALLOC(sizeof(char *), nsyms);
3092 NO_SPACE(symbol_type_tag);
3094 #endif
3096 v = TMALLOC(bucket *, nsyms);
3097 NO_SPACE(v);
3099 v[0] = 0;
3100 v[start_symbol] = 0;
3102 i = 1;
3103 j = (Value_t) (start_symbol + 1);
3104 for (bp = first_symbol; bp; bp = bp->next)
3106 if (bp->class == TERM)
3107 v[i++] = bp;
3108 else
3109 v[j++] = bp;
3111 assert(i == ntokens && j == nsyms);
3113 for (i = 1; i < ntokens; ++i)
3114 v[i]->index = i;
3116 goal->index = (Index_t) (start_symbol + 1);
3117 k = (Value_t) (start_symbol + 2);
3118 while (++i < nsyms)
3119 if (v[i] != goal)
3121 v[i]->index = k;
3122 ++k;
3125 goal->value = 0;
3126 k = 1;
3127 for (i = (Value_t) (start_symbol + 1); i < nsyms; ++i)
3129 if (v[i] != goal)
3131 v[i]->value = k;
3132 ++k;
3136 k = 0;
3137 for (i = 1; i < ntokens; ++i)
3139 n = v[i]->value;
3140 if (n > 256)
3142 for (j = k++; j > 0 && symbol_value[j - 1] > n; --j)
3143 symbol_value[j] = symbol_value[j - 1];
3144 symbol_value[j] = n;
3148 assert(v[1] != 0);
3150 if (v[1]->value == UNDEFINED)
3151 v[1]->value = 256;
3153 j = 0;
3154 n = 257;
3155 for (i = 2; i < ntokens; ++i)
3157 if (v[i]->value == UNDEFINED)
3159 while (j < k && n == symbol_value[j])
3161 while (++j < k && n == symbol_value[j])
3162 continue;
3163 ++n;
3165 v[i]->value = n;
3166 ++n;
3170 symbol_name[0] = name_pool + 8;
3171 symbol_value[0] = 0;
3172 symbol_prec[0] = 0;
3173 symbol_assoc[0] = TOKEN;
3174 #if defined(YYBTYACC)
3175 symbol_pval[0] = 0;
3176 max_tok_pval = 0;
3177 #endif
3178 for (i = 1; i < ntokens; ++i)
3180 symbol_name[i] = v[i]->name;
3181 symbol_value[i] = v[i]->value;
3182 symbol_prec[i] = v[i]->prec;
3183 symbol_assoc[i] = v[i]->assoc;
3184 #if defined(YYBTYACC)
3185 symbol_pval[i] = v[i]->value;
3186 if (symbol_pval[i] > max_tok_pval)
3187 max_tok_pval = symbol_pval[i];
3188 if (destructor)
3190 symbol_destructor[i] = v[i]->destructor;
3191 symbol_type_tag[i] = v[i]->tag;
3193 #endif
3195 symbol_name[start_symbol] = name_pool;
3196 symbol_value[start_symbol] = -1;
3197 symbol_prec[start_symbol] = 0;
3198 symbol_assoc[start_symbol] = TOKEN;
3199 #if defined(YYBTYACC)
3200 symbol_pval[start_symbol] = (Value_t) (max_tok_pval + 1);
3201 #endif
3202 for (++i; i < nsyms; ++i)
3204 k = v[i]->index;
3205 symbol_name[k] = v[i]->name;
3206 symbol_value[k] = v[i]->value;
3207 symbol_prec[k] = v[i]->prec;
3208 symbol_assoc[k] = v[i]->assoc;
3209 #if defined(YYBTYACC)
3210 symbol_pval[k] = (Value_t) ((max_tok_pval + 1) + v[i]->value + 1);
3211 if (destructor)
3213 symbol_destructor[k] = v[i]->destructor;
3214 symbol_type_tag[k] = v[i]->tag;
3216 #endif
3219 if (gflag)
3221 symbol_pname = TMALLOC(char *, nsyms);
3222 NO_SPACE(symbol_pname);
3224 for (i = 0; i < nsyms; ++i)
3225 protect_string(symbol_name[i], &(symbol_pname[i]));
3228 FREE(v);
3231 static void
3232 pack_grammar(void)
3234 int i;
3235 Value_t j;
3236 Assoc_t assoc;
3237 Value_t prec2;
3239 ritem = TMALLOC(Value_t, nitems);
3240 NO_SPACE(ritem);
3242 rlhs = TMALLOC(Value_t, nrules);
3243 NO_SPACE(rlhs);
3245 rrhs = TMALLOC(Value_t, nrules + 1);
3246 NO_SPACE(rrhs);
3248 rprec = TREALLOC(Value_t, rprec, nrules);
3249 NO_SPACE(rprec);
3251 rassoc = TREALLOC(Assoc_t, rassoc, nrules);
3252 NO_SPACE(rassoc);
3254 ritem[0] = -1;
3255 ritem[1] = goal->index;
3256 ritem[2] = 0;
3257 ritem[3] = -2;
3258 rlhs[0] = 0;
3259 rlhs[1] = 0;
3260 rlhs[2] = start_symbol;
3261 rrhs[0] = 0;
3262 rrhs[1] = 0;
3263 rrhs[2] = 1;
3265 j = 4;
3266 for (i = 3; i < nrules; ++i)
3268 #if defined(YYBTYACC)
3269 if (plhs[i]->args > 0)
3271 if (plhs[i]->argnames)
3273 FREE(plhs[i]->argnames);
3274 plhs[i]->argnames = NULL;
3276 if (plhs[i]->argtags)
3278 FREE(plhs[i]->argtags);
3279 plhs[i]->argtags = NULL;
3282 #endif /* defined(YYBTYACC) */
3283 rlhs[i] = plhs[i]->index;
3284 rrhs[i] = j;
3285 assoc = TOKEN;
3286 prec2 = 0;
3287 while (pitem[j])
3289 ritem[j] = pitem[j]->index;
3290 if (pitem[j]->class == TERM)
3292 prec2 = pitem[j]->prec;
3293 assoc = pitem[j]->assoc;
3295 ++j;
3297 ritem[j] = (Value_t) - i;
3298 ++j;
3299 if (rprec[i] == UNDEFINED)
3301 rprec[i] = prec2;
3302 rassoc[i] = assoc;
3305 rrhs[i] = j;
3307 FREE(plhs);
3308 FREE(pitem);
3309 #if defined(YYBTYACC)
3310 clean_arg_cache();
3311 #endif
3314 static void
3315 print_grammar(void)
3317 int i, k;
3318 size_t j, spacing = 0;
3319 FILE *f = verbose_file;
3321 if (!vflag)
3322 return;
3324 k = 1;
3325 for (i = 2; i < nrules; ++i)
3327 if (rlhs[i] != rlhs[i - 1])
3329 if (i != 2)
3330 fprintf(f, "\n");
3331 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
3332 spacing = strlen(symbol_name[rlhs[i]]) + 1;
3334 else
3336 fprintf(f, "%4d ", i - 2);
3337 j = spacing;
3338 while (j-- != 0)
3339 putc(' ', f);
3340 putc('|', f);
3343 while (ritem[k] >= 0)
3345 fprintf(f, " %s", symbol_name[ritem[k]]);
3346 ++k;
3348 ++k;
3349 putc('\n', f);
3353 #if defined(YYBTYACC)
3354 static void
3355 finalize_destructors(void)
3357 int i;
3358 bucket *bp;
3359 char *tag;
3361 for (i = 2; i < nsyms; ++i)
3363 tag = symbol_type_tag[i];
3364 if (symbol_destructor[i] == NULL)
3366 if (tag == NULL)
3367 { /* use <> destructor, if there is one */
3368 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3370 symbol_destructor[i] = TMALLOC(char,
3371 strlen(bp->destructor) + 1);
3372 NO_SPACE(symbol_destructor[i]);
3373 strcpy(symbol_destructor[i], bp->destructor);
3376 else
3377 { /* use type destructor for this tag, if there is one */
3378 bp = lookup_type_destructor(tag);
3379 if (bp->destructor != NULL)
3381 symbol_destructor[i] = TMALLOC(char,
3382 strlen(bp->destructor) + 1);
3383 NO_SPACE(symbol_destructor[i]);
3384 strcpy(symbol_destructor[i], bp->destructor);
3386 else
3387 { /* use <*> destructor, if there is one */
3388 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3389 /* replace "$$" with "(*val).tag" in destructor code */
3390 symbol_destructor[i]
3391 = process_destructor_XX(bp->destructor, tag);
3395 else
3396 { /* replace "$$" with "(*val)[.tag]" in destructor code */
3397 symbol_destructor[i]
3398 = process_destructor_XX(symbol_destructor[i], tag);
3401 /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */
3402 DO_FREE(symbol_type_tag); /* no longer needed */
3403 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3405 FREE(bp->name);
3406 /* 'bp->tag' is a static value, don't free */
3407 FREE(bp->destructor);
3408 FREE(bp);
3410 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3412 FREE(bp->name);
3413 /* 'bp->tag' is a static value, don't free */
3414 FREE(bp->destructor);
3415 FREE(bp);
3417 if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL)
3419 bucket *p;
3420 for (; bp; bp = p)
3422 p = bp->link;
3423 FREE(bp->name);
3424 /* 'bp->tag' freed by 'free_tags()' */
3425 FREE(bp->destructor);
3426 FREE(bp);
3430 #endif /* defined(YYBTYACC) */
3432 void
3433 reader(void)
3435 write_section(code_file, banner);
3436 create_symbol_table();
3437 read_declarations();
3438 read_grammar();
3439 free_symbol_table();
3440 pack_names();
3441 check_symbols();
3442 pack_symbols();
3443 pack_grammar();
3444 free_symbols();
3445 print_grammar();
3446 #if defined(YYBTYACC)
3447 if (destructor)
3448 finalize_destructors();
3449 #endif
3450 free_tags();
3453 #ifdef NO_LEAKS
3454 static param *
3455 free_declarations(param * list)
3457 while (list != 0)
3459 param *next = list->next;
3460 free(list->type);
3461 free(list->name);
3462 free(list->type2);
3463 free(list);
3464 list = next;
3466 return list;
3469 void
3470 reader_leaks(void)
3472 lex_param = free_declarations(lex_param);
3473 parse_param = free_declarations(parse_param);
3475 DO_FREE(line);
3476 DO_FREE(rrhs);
3477 DO_FREE(rlhs);
3478 DO_FREE(rprec);
3479 DO_FREE(ritem);
3480 DO_FREE(rassoc);
3481 DO_FREE(cache);
3482 DO_FREE(name_pool);
3483 DO_FREE(symbol_name);
3484 DO_FREE(symbol_prec);
3485 DO_FREE(symbol_assoc);
3486 DO_FREE(symbol_value);
3487 #if defined(YYBTYACC)
3488 DO_FREE(symbol_pval);
3489 DO_FREE(symbol_destructor);
3490 DO_FREE(symbol_type_tag);
3491 #endif
3493 #endif