1 /* $Id: reader.c,v 1.63 2016/06/07 00:17:51 tom Exp $ */
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. */
19 /* the maximum number of arguments (inherited attributes) to a non-terminal */
20 /* this is a hard limit, but seems more than adequate */
23 static void start_rule(bucket *bp, int s_lineno);
25 static void copy_destructor(void);
26 static char *process_destructor_XX(char *code, char *tag);
29 #define CACHE_SIZE 256
31 static int cinc, cache_size;
34 static int tagmax, havetags;
35 static char **tag_table;
45 static char last_was_action;
47 static int trialaction;
51 static bucket **pitem;
56 static size_t name_pool_size;
57 static char *name_pool;
59 char line_format[] = "#line %d \"%s\"\n";
65 int destructor = 0; /* =1 if at least one %destructor */
67 static bucket *default_destructor[3] =
70 #define UNTYPED_DEFAULT 0
71 #define TYPED_DEFAULT 1
72 #define TYPE_SPECIFIED 2
75 lookup_type_destructor(char *tag)
77 const char fmt[] = "%.*s destructor";
78 char name[1024] = "\0";
79 bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED];
81 while ((bp = *bpp) != NULL)
88 sprintf(name, fmt, (int)(sizeof(name) - sizeof(fmt)), tag);
89 *bpp = bp = make_bucket(name);
94 #endif /* defined(YYBTYACC) */
100 if (cinc >= cache_size)
102 cache_size += CACHE_SIZE;
103 cache = TREALLOC(char, cache, cache_size);
106 cache[cinc] = (char)c;
113 FILE *f = input_file;
117 if (saw_eof || (c = getc(f)) == EOF)
129 if (line == NULL || linesize != (LINESIZE + 1))
133 linesize = LINESIZE + 1;
134 line = TMALLOC(char, linesize);
145 if ((i + 3) >= linesize)
147 linesize += LINESIZE;
148 line = TREALLOC(char, line, linesize);
174 p = TMALLOC(char, s - line + 1);
179 while ((*t++ = *s++) != '\n')
189 int st_lineno = lineno;
190 char *st_line = dup_line();
191 char *st_cptr = st_line + (cptr - line);
196 if (*s == '*' && s[1] == '/')
206 unterminated_comment(st_lineno, st_line, st_cptr);
239 else if (s[1] == '/')
264 switch (ch = next_inline())
291 static struct keyword
297 { "binary", NONASSOC },
298 #if defined(YYBTYACC)
299 { "destructor", DESTRUCTOR },
301 { "expect", EXPECT },
302 { "expect-rr", EXPECT_RR },
305 { "lex-param", LEX_PARAM },
306 #if defined(YYBTYACC)
307 { "locations", LOCATIONS },
309 { "nonassoc", NONASSOC },
310 { "parse-param", PARSE_PARAM },
311 { "pure-parser", PURE_PARSER },
316 { "token-table", TOKEN_TABLE },
319 { "yacc", POSIX_YACC },
324 compare_keys(const void *a, const void *b)
326 const struct keyword *p = (const struct keyword *)a;
327 const struct keyword *q = (const struct keyword *)b;
328 return strcmp(p->name, q->name);
359 /* treat keywords spelled with '_' as if it were '-' */
370 if ((key = bsearch(cache, keywords,
371 sizeof(keywords) / sizeof(*key),
372 sizeof(*key), compare_keys)))
380 if (c == '%' || c == '\\')
391 syntax_error(lineno, line, t_cptr);
399 FILE *f = output_file;
405 syntax_error(lineno, line, cptr);
407 fprintf(f, "#ident \"");
427 copy_string(int quote)
429 struct mstring *temp = msnew();
431 int s_lineno = lineno;
432 char *s_line = dup_line();
433 char *s_cptr = s_line + (cptr - line - 1);
445 unterminated_string(s_lineno, s_line, s_cptr);
454 unterminated_string(s_lineno, s_line, s_cptr);
463 struct mstring *temp = msnew();
470 while ((c = *++cptr) != '\n')
473 if (c == '*' && cptr[1] == '/')
481 int c_lineno = lineno;
482 char *c_line = dup_line();
483 char *c_cptr = c_line + (cptr - line - 1);
491 if (c == '*' && *cptr == '/')
502 unterminated_comment(c_lineno, c_line, c_cptr);
514 int need_newline = 0;
515 int t_lineno = lineno;
516 char *t_line = dup_line();
517 char *t_cptr = t_line + (cptr - line - 2);
523 unterminated_text(t_lineno, t_line, t_cptr);
526 fprintf(f, line_format, lineno, input_file_name);
538 unterminated_text(t_lineno, t_line, t_cptr);
544 char *s = copy_string(c);
554 char *s = copy_comment();
581 puts_both(const char *s)
585 fputs(s, union_file);
601 int u_lineno = lineno;
602 char *u_line = dup_line();
603 char *u_cptr = u_line + (cptr - line - 6);
606 over_unionized(cptr - 6);
609 puts_both("#ifdef YYSTYPE\n");
610 puts_both("#undef YYSTYPE_IS_DECLARED\n");
611 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
612 puts_both("#endif\n");
613 puts_both("#ifndef YYSTYPE_IS_DECLARED\n");
614 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
617 fprintf(text_file, line_format, lineno, input_file_name);
618 puts_both("typedef union");
629 unterminated_union(u_lineno, u_line, u_cptr);
639 puts_both(" YYSTYPE;\n");
640 puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n");
649 char *s = copy_string(c);
657 char *s = copy_comment();
669 after_blanks(char *s)
671 while (*s != '\0' && isspace(UCH(*s)))
677 * Trim leading/trailing blanks, and collapse multiple embedded blanks to a
678 * single space. Return index to last character in the buffer.
681 trim_blanks(char *buffer)
686 char *s = after_blanks(d);
688 while ((*d++ = *s++) != '\0')
694 while ((--d != buffer) && isspace(UCH(*d)))
697 for (s = d = buffer; (*d++ = *s++) != '\0';)
699 if (isspace(UCH(*s)))
702 while (isspace(UCH(*s)))
711 return (int)strlen(buffer) - 1;
715 * Scan forward in the current line-buffer looking for a right-curly bracket.
717 * Parameters begin with a left-curly bracket, and continue until there are no
718 * more interesting characters after the last right-curly bracket on the
719 * current line. Bison documents parameters as separated like this:
720 * {type param1} {type2 param2}
721 * but also accepts commas (although some versions of bison mishandle this)
722 * {type param1, type2 param2}
732 switch (next_inline())
751 save_param(int k, char *buffer, int name, int type2)
755 p = TMALLOC(param, 1);
758 p->type2 = strdup(buffer + type2);
760 buffer[type2] = '\0';
761 (void)trim_blanks(p->type2);
763 p->name = strdup(buffer + name);
766 (void)trim_blanks(p->name);
768 p->type = strdup(buffer);
770 (void)trim_blanks(p->type);
794 * Keep a linked list of parameters. This may be multi-line, if the trailing
795 * right-curly bracket is absent.
806 int st_lineno = lineno;
840 if ((curly == 1) && (cptr == line))
850 if (curly == 0 && !isspace(UCH(c)))
858 buf_size = (size_t) linesize;
859 buf = TMALLOC(char, buf_size);
867 buf_size += (size_t) linesize;
868 buf = TREALLOC(char, buf, buf_size);
873 if ((state == 2) && (c == L_CURL))
877 else if ((state == 2) && isspace(UCH(c)))
881 else if ((c != L_CURL) && (c != R_CURL))
888 while (curly < 2 || more_curly());
901 (void)trim_blanks(buf);
906 char *parms = (comma + 1);
907 comma = strchr(parms, ',');
911 (void)trim_blanks(parms);
912 i = (int)strlen(parms) - 1;
921 while (i >= 0 && level > 0 && parms[i] != '[')
925 else if (parms[i] == '[')
938 while (i > 0 && (isalnum(UCH(parms[i])) || UCH(parms[i]) == '_'))
941 if (!isspace(UCH(parms[i])) && parms[i] != '*')
946 save_param(k, parms, name, type2);
954 syntax_error(lineno, line, cptr);
960 if (c >= '0' && c <= '9')
962 if (c >= 'A' && c <= 'F')
963 return (c - 'A' + 10);
964 if (c >= 'a' && c <= 'f')
965 return (c - 'a' + 10);
977 int s_lineno = lineno;
978 char *s_line = dup_line();
979 char *s_cptr = s_line + (cptr - line);
989 unterminated_string(s_lineno, s_line, s_cptr);
992 char *c_cptr = cptr - 1;
1000 unterminated_string(s_lineno, s_line, s_cptr);
1015 n = (n << 3) + (c - '0');
1019 n = (n << 3) + (c - '0');
1024 illegal_character(c_cptr);
1031 if (n < 0 || n >= 16)
1032 illegal_character(c_cptr);
1037 if (i < 0 || i >= 16)
1042 illegal_character(c_cptr);
1075 s = TMALLOC(char, n);
1078 for (i = 0; i < n; ++i)
1087 for (i = 0; i < n; ++i)
1090 if (c == '\\' || c == cache[0])
1095 else if (isprint(c))
1124 cachec(((c >> 6) & 7) + '0');
1125 cachec(((c >> 3) & 7) + '0');
1126 cachec((c & 7) + '0');
1140 if (n == 1 && bp->value == UNDEFINED)
1141 bp->value = UCH(*s);
1148 is_reserved(char *name)
1152 if (strcmp(name, ".") == 0 ||
1153 strcmp(name, "$accept") == 0 ||
1154 strcmp(name, "$end") == 0)
1157 if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2])))
1160 while (isdigit(UCH(*s)))
1175 for (c = *cptr; IS_IDENT(c); c = *++cptr)
1179 if (is_reserved(cache))
1180 used_reserved(cache);
1182 return (lookup(cache));
1192 for (c = *cptr; isdigit(c); c = *++cptr)
1193 n = (Value_t)(10 * n + (c - '0'));
1199 cache_tag(char *tag, size_t len)
1204 for (i = 0; i < ntags; ++i)
1206 if (strncmp(tag, tag_table[i], len) == 0 &&
1207 tag_table[i][len] == NUL)
1208 return (tag_table[i]);
1211 if (ntags >= tagmax)
1216 ? TREALLOC(char *, tag_table, tagmax)
1217 : TMALLOC(char *, tagmax));
1218 NO_SPACE(tag_table);
1221 s = TMALLOC(char, len + 1);
1224 strncpy(s, tag, len);
1226 tag_table[ntags++] = s;
1234 int t_lineno = lineno;
1235 char *t_line = dup_line();
1236 char *t_cptr = t_line + (cptr - line);
1242 if (!isalpha(c) && c != '_' && c != '$')
1243 illegal_tag(t_lineno, t_line, t_cptr);
1251 while (IS_IDENT(c));
1258 illegal_tag(t_lineno, t_line, t_cptr);
1263 return cache_tag(cache, (size_t) cinc);
1266 #if defined(YYBTYACC)
1272 while (isalnum(*cptr) || *cptr == '_' || *cptr == '$')
1274 return cache_tag(b, (size_t) (cptr - b));
1279 declare_tokens(int assoc)
1302 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1304 else if (c == '\'' || c == '"')
1310 tokenized_start(bp->name);
1315 if (bp->tag && tag != bp->tag)
1316 retyped_warning(bp->name);
1322 if (bp->prec && prec != bp->prec)
1323 reprec_warning(bp->name);
1324 bp->assoc = (Assoc_t)assoc;
1335 value = get_number();
1336 if (bp->value != UNDEFINED && value != bp->value)
1337 revalued_warning(bp->name);
1347 * %expect requires special handling
1348 * as it really isn't part of the yacc
1349 * grammar only a flag for yacc proper.
1352 declare_expect(int assoc)
1356 if (assoc != EXPECT && assoc != EXPECT_RR)
1360 * Stay away from nextc - doesn't
1361 * detect EOL and will read to EOF.
1371 if (assoc == EXPECT)
1372 SRexpect = get_number();
1374 RRexpect = get_number();
1378 * Looking for number before EOL.
1379 * Spaces, tabs, and numbers are ok,
1380 * words, punc., etc. are syntax errors.
1382 else if (c == '\n' || isalpha(c) || !isspace(c))
1384 syntax_error(lineno, line, cptr);
1395 #if defined(YYBTYACC)
1397 declare_argtypes(bucket *bp)
1399 char *tags[MAXARGS];
1403 retyped_warning(bp->name);
1404 cptr++; /* skip open paren */
1411 syntax_error(lineno, line, cptr);
1412 tags[args++] = get_tag();
1419 cptr++; /* skip close paren */
1421 bp->argnames = TMALLOC(char *, args);
1422 NO_SPACE(bp->argnames);
1423 bp->argtags = CALLOC(sizeof(char *), args + 1);
1424 NO_SPACE(bp->argtags);
1427 bp->argtags[args] = tags[args];
1428 bp->argnames[args] = NULL;
1451 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1454 #if defined(YYBTYACC)
1455 if (nextc() == L_PAREN)
1456 declare_argtypes(bp);
1461 else if (c == '\'' || c == '"')
1464 #if defined(YYBTYACC)
1473 if (bp->tag && tag != bp->tag)
1474 retyped_warning(bp->name);
1489 if (!isalpha(c) && c != '_' && c != '.' && c != '$')
1490 syntax_error(lineno, line, cptr);
1492 if (bp->class == TERM)
1493 terminal_start(bp->name);
1494 if (goal && goal != bp)
1495 restarted_warning();
1500 read_declarations(void)
1504 cache_size = CACHE_SIZE;
1505 cache = TMALLOC(char, cache_size);
1514 syntax_error(lineno, line, cptr);
1515 switch (k = keyword())
1565 #if defined(YYBTYACC)
1577 /* noop for bison compatibility. byacc is already designed to be posix
1578 * yacc compatible. */
1585 initialize_grammar(void)
1590 pitem = TMALLOC(bucket *, maxitems);
1601 plhs = TMALLOC(bucket *, maxrules);
1608 rprec = TMALLOC(Value_t, maxrules);
1615 rassoc = TMALLOC(Assoc_t, maxrules);
1627 pitem = TREALLOC(bucket *, pitem, maxitems);
1636 plhs = TREALLOC(bucket *, plhs, maxrules);
1639 rprec = TREALLOC(Value_t, rprec, maxrules);
1642 rassoc = TREALLOC(Assoc_t, rassoc, maxrules);
1646 /* set immediately prior to where copy_args() could be called, and incremented by
1647 the various routines that will rescan the argument list as appropriate */
1648 static int rescan_lineno;
1649 #if defined(YYBTYACC)
1652 copy_args(int *alen)
1654 struct mstring *s = msnew();
1655 int depth = 0, len = 1;
1657 int a_lineno = lineno;
1658 char *a_line = dup_line();
1659 char *a_cptr = a_line + (cptr - line - 1);
1661 while ((c = *cptr++) != R_PAREN || depth || quote)
1663 if (c == ',' && !quote && !depth)
1676 unterminated_string(a_lineno, a_line, a_cptr);
1678 unterminated_arglist(a_lineno, a_line, a_cptr);
1695 else if (c == R_PAREN)
1697 else if (c == '\"' || c == '\'')
1708 parse_id(char *p, char **save)
1715 if (!isalpha(*p) && *p != '_')
1718 while (isalnum(*p) || *p == '_' || *p == '$')
1722 *save = cache_tag(b, (size_t) (p - b));
1728 parse_int(char *p, int *save)
1730 int neg = 0, val = 0;
1743 val = val * 10 + *p++ - '0';
1752 parse_arginfo(bucket *a, char *args, int argslen)
1754 char *p = args, *tmp;
1759 if (a->args != argslen)
1760 arg_number_disagree_warning(rescan_lineno, a->name);
1765 if ((a->args = argslen) == 0)
1767 a->argnames = TMALLOC(char *, argslen);
1768 NO_SPACE(a->argnames);
1769 a->argtags = TMALLOC(char *, argslen);
1770 NO_SPACE(a->argtags);
1774 for (i = 0; i < argslen; i++)
1787 if (!(p = parse_id(p + 1, &tmp)))
1796 if (a->argtags[i] != tmp)
1797 arg_type_disagree_warning(rescan_lineno, i + 1, a->name);
1800 a->argtags[i] = tmp;
1803 a->argtags[i] = NULL;
1804 if (!(p = parse_id(p, &a->argnames[i])))
1816 compile_arg(char **theptr, char *yyvaltag)
1819 struct mstring *c = msnew();
1821 Value_t *offsets = NULL, maxoffset;
1826 for (i = nitems - 1; pitem[i]; --i)
1829 if (pitem[i]->class != ARGUMENT)
1834 offsets = TMALLOC(Value_t, maxoffset + 1);
1837 for (j = 0, i++; i < nitems; i++)
1838 if (pitem[i]->class != ARGUMENT)
1839 offsets[++j] = (Value_t)(i - nitems + 1);
1841 rhs = pitem + nitems - 1;
1844 msprintf(c, "yyval.%s = ", yyvaltag);
1846 msprintf(c, "yyval = ");
1853 if (!(p = parse_id(++p, &tag)) || *p++ != '>')
1854 illegal_tag(rescan_lineno, NULL, NULL);
1855 if (isdigit(*p) || *p == '-')
1858 if (!(p = parse_int(p, &val)))
1859 dollar_error(rescan_lineno, NULL, NULL);
1862 else if (val > maxoffset)
1864 dollar_warning(rescan_lineno, val);
1865 i = val - maxoffset;
1867 else if (maxoffset > 0)
1870 if (!tag && !(tag = rhs[i]->tag) && havetags)
1871 untyped_rhs(val, rhs[i]->name);
1873 msprintf(c, "yystack.l_mark[%d]", i);
1875 msprintf(c, ".%s", tag);
1879 else if (isalpha(*p) || *p == '_')
1882 if (!(p = parse_id(p, &arg)))
1883 dollar_error(rescan_lineno, NULL, NULL);
1884 for (i = plhs[nrules]->args - 1; i >= 0; i--)
1885 if (arg == plhs[nrules]->argnames[i])
1888 unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL);
1890 tag = plhs[nrules]->argtags[i];
1891 msprintf(c, "yystack.l_mark[%d]",
1892 i - plhs[nrules]->args + 1 - n);
1894 msprintf(c, ".%s", tag);
1896 untyped_arg_warning(rescan_lineno, "$", arg);
1899 dollar_error(rescan_lineno, NULL, NULL);
1903 at_error(rescan_lineno, NULL, NULL);
1919 can_elide_arg(char **theptr, char *yyvaltag)
1924 Value_t *offsets = NULL, maxoffset = 0;
1932 if (!(p = parse_id(++p, &tag)) || *p++ != '>')
1935 for (i = nitems - 1; pitem[i]; --i)
1938 if (pitem[i]->class != ARGUMENT)
1943 offsets = TMALLOC(Value_t, maxoffset + 1);
1946 for (j = 0, i++; i < nitems; i++)
1947 if (pitem[i]->class != ARGUMENT)
1948 offsets[++j] = (Value_t)(i - nitems + 1);
1950 rhs = pitem + nitems - 1;
1952 if (isdigit(*p) || *p == '-')
1955 if (!(p = parse_int(p, &val)))
1961 else if (val > maxoffset)
1972 else if (isalpha(*p) || *p == '_')
1975 if (!(p = parse_id(p, &arg)))
1977 for (i = plhs[nrules]->args - 1; i >= 0; i--)
1978 if (arg == plhs[nrules]->argnames[i])
1983 tag = plhs[nrules]->argtags[i];
1984 rv = plhs[nrules]->args + n - i;
1987 if (tag && yyvaltag)
1989 if (strcmp(tag, yyvaltag))
1992 else if (tag || yyvaltag)
2002 #define ARG_CACHE_SIZE 1024
2003 static struct arg_cache
2005 struct arg_cache *next;
2009 *arg_cache[ARG_CACHE_SIZE];
2012 lookup_arg_cache(char *code)
2014 struct arg_cache *entry;
2016 entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE];
2019 if (!strnscmp(entry->code, code))
2021 entry = entry->next;
2027 insert_arg_cache(char *code, int rule)
2029 struct arg_cache *entry = NEW(struct arg_cache);
2033 i = strnshash(code) % ARG_CACHE_SIZE;
2036 entry->next = arg_cache[i];
2037 arg_cache[i] = entry;
2041 clean_arg_cache(void)
2043 struct arg_cache *e, *t;
2046 for (i = 0; i < ARG_CACHE_SIZE; i++)
2048 for (e = arg_cache[i]; (t = e); e = e->next, FREE(t))
2050 arg_cache[i] = NULL;
2053 #endif /* defined(YYBTYACC) */
2056 advance_to_start(void)
2062 #if defined(YYBTYACC)
2087 syntax_error(lineno, line, s_cptr);
2092 if (!isalpha(c) && c != '_' && c != '.' && c != '_')
2093 syntax_error(lineno, line, cptr);
2097 if (bp->class == TERM)
2098 terminal_start(bp->name);
2106 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2107 #if defined(YYBTYACC)
2111 args = copy_args(&argslen);
2117 syntax_error(lineno, line, cptr);
2118 start_rule(bp, s_lineno);
2119 #if defined(YYBTYACC)
2120 parse_arginfo(bp, args, argslen);
2126 start_rule(bucket *bp, int s_lineno)
2128 if (bp->class == TERM)
2129 terminal_lhs(s_lineno);
2130 bp->class = NONTERM;
2133 if (nrules >= maxrules)
2136 rprec[nrules] = UNDEFINED;
2137 rassoc[nrules] = TOKEN;
2145 if (!last_was_action && plhs[nrules]->tag)
2147 if (pitem[nitems - 1])
2149 for (i = nitems - 1; (i > 0) && pitem[i]; --i)
2151 if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag)
2152 default_action_warning(plhs[nrules]->name);
2155 default_action_warning(plhs[nrules]->name);
2158 last_was_action = 0;
2159 if (nitems >= maxitems)
2167 insert_empty_rule(void)
2172 assert(cache_size >= CACHE_SIZE);
2173 sprintf(cache, "$$%d", ++gensym);
2174 bp = make_bucket(cache);
2175 last_symbol->next = bp;
2177 bp->tag = plhs[nrules]->tag;
2179 #if defined(YYBTYACC)
2183 nitems = (Value_t)(nitems + 2);
2184 if (nitems > maxitems)
2186 bpp = pitem + nitems - 1;
2188 while ((bpp[0] = bpp[-1]) != 0)
2191 if (++nrules >= maxrules)
2193 plhs[nrules] = plhs[nrules - 1];
2194 plhs[nrules - 1] = bp;
2195 rprec[nrules] = rprec[nrules - 1];
2196 rprec[nrules - 1] = 0;
2197 rassoc[nrules] = rassoc[nrules - 1];
2198 rassoc[nrules - 1] = TOKEN;
2201 #if defined(YYBTYACC)
2203 insert_arg_rule(char *arg, char *tag)
2205 int line_number = rescan_lineno;
2206 char *code = compile_arg(&arg, tag);
2207 int rule = lookup_arg_cache(code);
2208 FILE *f = action_file;
2213 insert_arg_cache(code, rule);
2214 trialaction = 1; /* arg rules always run in trial mode */
2215 fprintf(f, "case %d:\n", rule - 2);
2217 fprintf(f, line_format, line_number, input_file_name);
2218 fprintf(f, "%s;\n", code);
2219 fprintf(f, "break;\n");
2220 insert_empty_rule();
2221 plhs[rule]->tag = cache_tag(tag, strlen(tag));
2222 plhs[rule]->class = ARGUMENT;
2226 if (++nitems > maxitems)
2228 pitem[nitems - 1] = plhs[rule];
2240 int s_lineno = lineno;
2241 #if defined(YYBTYACC)
2247 if (c == '\'' || c == '"')
2253 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2254 #if defined(YYBTYACC)
2258 args = copy_args(&argslen);
2266 start_rule(bp, s_lineno);
2267 #if defined(YYBTYACC)
2268 parse_arginfo(bp, args, argslen);
2274 if (last_was_action)
2275 insert_empty_rule();
2276 last_was_action = 0;
2278 #if defined(YYBTYACC)
2281 if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL)
2284 if (plhs[nrules]->args != bp->args)
2285 wrong_number_args_warning("default ", bp->name);
2286 for (i = bp->args - 1; i >= 0; i--)
2287 if (plhs[nrules]->argtags[i] != bp->argtags[i])
2288 wrong_type_for_arg_warning(i + 1, bp->name);
2290 else if (bp->args != argslen)
2291 wrong_number_args_warning("", bp->name);
2296 int elide_cnt = can_elide_arg(&ap, bp->argtags[0]);
2298 if (elide_cnt > argslen)
2302 for (i = 1; i < elide_cnt; i++)
2303 if (can_elide_arg(&ap, bp->argtags[i]) != elide_cnt - i)
2311 assert(i == elide_cnt);
2318 for (; i < argslen; i++)
2319 ap = insert_arg_rule(ap, bp->argtags[i]);
2322 #endif /* defined(YYBTYACC) */
2324 if (++nitems > maxitems)
2326 pitem[nitems - 1] = bp;
2335 #if defined(YYBTYACC)
2339 FILE *f = action_file;
2340 int a_lineno = lineno;
2341 char *a_line = dup_line();
2342 char *a_cptr = a_line + (cptr - line);
2343 Value_t *offsets = NULL, maxoffset;
2346 if (last_was_action)
2347 insert_empty_rule();
2348 last_was_action = 1;
2349 #if defined(YYBTYACC)
2350 trialaction = (*cptr == L_BRAC);
2353 fprintf(f, "case %d:\n", nrules - 2);
2354 #if defined(YYBTYACC)
2358 fprintf(f, " if (!yytrial)\n");
2362 fprintf(f, line_format, lineno, input_file_name);
2366 /* avoid putting curly-braces in first column, to ease editing */
2367 if (*after_blanks(cptr) == L_CURL)
2370 cptr = after_blanks(cptr);
2375 for (i = nitems - 1; pitem[i]; --i)
2378 if (pitem[i]->class != ARGUMENT)
2383 offsets = TMALLOC(Value_t, maxoffset + 1);
2386 for (j = 0, i++; i < nitems; i++)
2388 if (pitem[i]->class != ARGUMENT)
2390 offsets[++j] = (Value_t)(i - nitems + 1);
2394 rhs = pitem + nitems - 1;
2403 int d_lineno = lineno;
2404 char *d_line = dup_line();
2405 char *d_cptr = d_line + (cptr - line);
2412 fprintf(f, "yyval.%s", tag);
2417 else if (isdigit(c))
2421 fprintf(f, "yystack.l_mark[%d].%s", -n, tag);
2422 else if (i > maxoffset)
2424 dollar_warning(d_lineno, i);
2425 fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag);
2428 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2432 else if (c == '-' && isdigit(UCH(cptr[1])))
2435 i = -get_number() - n;
2436 fprintf(f, "yystack.l_mark[%d].%s", i, tag);
2440 #if defined(YYBTYACC)
2441 else if (isalpha(c) || c == '_')
2443 char *arg = scan_id();
2444 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2445 if (arg == plhs[nrules]->argnames[i])
2448 unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr);
2449 fprintf(f, "yystack.l_mark[%d].%s",
2450 i - plhs[nrules]->args + 1 - n, tag);
2456 dollar_error(d_lineno, d_line, d_cptr);
2458 else if (cptr[1] == '$')
2462 tag = plhs[nrules]->tag;
2465 fprintf(f, "yyval.%s", tag);
2468 fprintf(f, "yyval");
2470 #if defined(YYBTYACC)
2475 else if (isdigit(UCH(cptr[1])))
2479 if (havetags && offsets)
2481 if (i <= 0 || i > maxoffset)
2483 tag = rhs[offsets[i]]->tag;
2485 untyped_rhs(i, rhs[offsets[i]]->name);
2486 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2491 fprintf(f, "yystack.l_mark[%d]", -n);
2492 else if (i > maxoffset)
2494 dollar_warning(lineno, i);
2495 fprintf(f, "yystack.l_mark[%d]", i - maxoffset);
2498 fprintf(f, "yystack.l_mark[%d]", offsets[i]);
2502 else if (cptr[1] == '-')
2508 fprintf(f, "yystack.l_mark[%d]", -i - n);
2511 #if defined(YYBTYACC)
2512 else if (isalpha(cptr[1]) || cptr[1] == '_')
2517 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2518 if (arg == plhs[nrules]->argnames[i])
2521 unknown_arg_warning(lineno, "$", arg, line, cptr);
2522 tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]);
2523 fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n);
2525 fprintf(f, ".%s", tag);
2527 untyped_arg_warning(lineno, "$", arg);
2532 #if defined(YYBTYACC)
2537 int l_lineno = lineno;
2538 char *l_line = dup_line();
2539 char *l_cptr = l_line + (cptr - line);
2540 syntax_error(l_lineno, l_line, l_cptr);
2544 fprintf(f, "yyloc");
2548 else if (isdigit(UCH(cptr[1])))
2553 fprintf(f, "yystack.p_mark[%d]", -n);
2554 else if (i > maxoffset)
2556 at_warning(lineno, i);
2557 fprintf(f, "yystack.p_mark[%d]", i - maxoffset);
2560 fprintf(f, "yystack.p_mark[%d]", offsets[i]);
2563 else if (cptr[1] == '-')
2567 fprintf(f, "yystack.p_mark[%d]", -i - n);
2572 if (isalpha(c) || c == '_' || c == '$')
2579 while (isalnum(c) || c == '_' || c == '$');
2583 #if defined(YYBTYACC)
2586 if (trialaction && c == L_BRAC && depth == 0)
2592 if (trialaction && c == R_BRAC && depth == 1)
2597 if (c == L_BRAC && !haveyyval)
2601 if (c == L_CURL && !haveyyval)
2603 fprintf(f, " if (!yytrial)\n");
2605 fprintf(f, line_format, lineno, input_file_name);
2609 fprintf(f, "\nbreak;\n");
2624 unterminated_action(a_lineno, a_line, a_cptr);
2629 fprintf(f, "\nbreak;\n");
2635 #if defined(YYBTYACC)
2654 #if defined(YYBTYACC)
2658 if (c == L_BRAC && !haveyyval)
2663 if (c == L_CURL && !haveyyval)
2665 fprintf(f, " if (!yytrial)\n");
2667 fprintf(f, line_format, lineno, input_file_name);
2672 fprintf(f, "\nbreak;\n");
2681 char *s = copy_string(c);
2689 char *s = copy_comment();
2700 #if defined(YYBTYACC)
2702 copy_destructor(void)
2708 struct mstring *destructor_text = msnew();
2715 msprintf(destructor_text, line_format, lineno, input_file_name);
2717 cptr = after_blanks(cptr);
2718 if (*cptr == L_CURL)
2719 /* avoid putting curly-braces in first column, to ease editing */
2720 mputc(destructor_text, '\t');
2722 syntax_error(lineno, line, cptr);
2725 a_line = dup_line();
2726 a_cptr = a_line + (cptr - line);
2735 int d_lineno = lineno;
2736 char *d_line = dup_line();
2737 char *d_cptr = d_line + (cptr - line);
2744 msprintf(destructor_text, "(*val).%s", tag);
2750 dollar_error(d_lineno, d_line, d_cptr);
2752 else if (cptr[1] == '$')
2754 /* process '$$' later; replacement is context dependent */
2755 msprintf(destructor_text, "$$");
2760 if (c == '@' && cptr[1] == '$')
2764 int l_lineno = lineno;
2765 char *l_line = dup_line();
2766 char *l_cptr = l_line + (cptr - line);
2767 syntax_error(l_lineno, l_line, l_cptr);
2769 msprintf(destructor_text, "(*loc)");
2773 if (isalpha(c) || c == '_' || c == '$')
2777 mputc(destructor_text, c);
2780 while (isalnum(c) || c == '_' || c == '$');
2784 mputc(destructor_text, c);
2791 unterminated_action(a_lineno, a_line, a_cptr);
2800 goto process_symbols;
2805 char *s = copy_string(c);
2806 msprintf(destructor_text, "%s", s);
2813 char *s = copy_comment();
2814 msprintf(destructor_text, "%s", s);
2823 code_text = msdone(destructor_text);
2832 { /* "no semantic type" default destructor */
2834 if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL)
2836 static char untyped_default[] = "<>";
2837 bp = make_bucket("untyped default");
2838 bp->tag = untyped_default;
2839 default_destructor[UNTYPED_DEFAULT] = bp;
2841 if (bp->destructor != NULL)
2842 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2844 /* replace "$$" with "(*val)" in destructor code */
2845 bp->destructor = process_destructor_XX(code_text, NULL);
2847 else if (cptr[1] == '*' && cptr[2] == '>')
2848 { /* "no per-symbol or per-type" default destructor */
2850 if ((bp = default_destructor[TYPED_DEFAULT]) == NULL)
2852 static char typed_default[] = "<*>";
2853 bp = make_bucket("typed default");
2854 bp->tag = typed_default;
2855 default_destructor[TYPED_DEFAULT] = bp;
2857 if (bp->destructor != NULL)
2858 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2861 /* postpone re-processing destructor $$s until end of grammar spec */
2862 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2863 NO_SPACE(bp->destructor);
2864 strcpy(bp->destructor, code_text);
2868 { /* "semantic type" default destructor */
2870 bp = lookup_type_destructor(tag);
2871 if (bp->destructor != NULL)
2872 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2874 /* replace "$$" with "(*val).tag" in destructor code */
2875 bp->destructor = process_destructor_XX(code_text, tag);
2878 else if (isalpha(c) || c == '_' || c == '.' || c == '$')
2879 { /* "symbol" destructor */
2881 if (bp->destructor != NULL)
2882 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2885 /* postpone re-processing destructor $$s until end of grammar spec */
2886 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2887 NO_SPACE(bp->destructor);
2888 strcpy(bp->destructor, code_text);
2899 process_destructor_XX(char *code, char *tag)
2904 struct mstring *new_code = msnew();
2905 char *codeptr = code;
2908 loop: /* step thru code */
2910 if (c == '$' && codeptr[1] == '$')
2914 msprintf(new_code, "(*val)");
2916 msprintf(new_code, "(*val).%s", tag);
2919 if (isalpha(c) || c == '_' || c == '$')
2926 while (isalnum(c) || c == '_' || c == '$');
2940 return msdone(new_code);
2968 if (c == '*' && *codeptr == '/')
2970 mputc(new_code, '/');
2982 #endif /* defined(YYBTYACC) */
2991 if (c == '%' || c == '\\')
2999 else if ((c == 'p' || c == 'P') &&
3000 ((c = cptr[2]) == 'r' || c == 'R') &&
3001 ((c = cptr[3]) == 'e' || c == 'E') &&
3002 ((c = cptr[4]) == 'c' || c == 'C') &&
3003 ((c = cptr[5], !IS_IDENT(c))))
3006 syntax_error(lineno, line, cptr);
3009 if (isalpha(c) || c == '_' || c == '.' || c == '$')
3011 else if (c == '\'' || c == '"')
3015 syntax_error(lineno, line, cptr);
3019 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
3022 rprec[nrules] = bp->prec;
3023 rassoc[nrules] = bp->assoc;
3032 initialize_grammar();
3047 #if defined(YYBTYACC)
3048 else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC))
3050 else if (c == L_CURL || c == '=')
3056 start_rule(plhs[nrules - 1], 0);
3065 syntax_error(lineno, line, cptr);
3068 #if defined(YYBTYACC)
3070 start_requires_args(goal->name);
3082 for (i = 0; i < ntags; ++i)
3084 assert(tag_table[i]);
3096 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
3097 for (bp = first_symbol; bp; bp = bp->next)
3098 name_pool_size += strlen(bp->name) + 1;
3100 name_pool = TMALLOC(char, name_pool_size);
3101 NO_SPACE(name_pool);
3103 strcpy(name_pool, "$accept");
3104 strcpy(name_pool + 8, "$end");
3106 for (bp = first_symbol; bp; bp = bp->next)
3110 while ((*t++ = *s++) != 0)
3122 if (goal->class == UNKNOWN)
3123 undefined_goal(goal->name);
3125 for (bp = first_symbol; bp; bp = bp->next)
3127 if (bp->class == UNKNOWN)
3129 undefined_symbol_warning(bp->name);
3136 protect_string(char *src, char **des)
3149 if ('\\' == *s || '"' == *s)
3155 *des = d = TMALLOC(char, len);
3161 if ('\\' == *s || '"' == *s)
3175 #if defined(YYBTYACC)
3176 Value_t max_tok_pval;
3181 for (bp = first_symbol; bp; bp = bp->next)
3184 if (bp->class == TERM)
3187 start_symbol = (Value_t)ntokens;
3188 nvars = (Value_t)(nsyms - ntokens);
3190 symbol_name = TMALLOC(char *, nsyms);
3191 NO_SPACE(symbol_name);
3193 symbol_value = TMALLOC(Value_t, nsyms);
3194 NO_SPACE(symbol_value);
3196 symbol_prec = TMALLOC(Value_t, nsyms);
3197 NO_SPACE(symbol_prec);
3199 symbol_assoc = TMALLOC(char, nsyms);
3200 NO_SPACE(symbol_assoc);
3202 #if defined(YYBTYACC)
3203 symbol_pval = TMALLOC(Value_t, nsyms);
3204 NO_SPACE(symbol_pval);
3208 symbol_destructor = CALLOC(sizeof(char *), nsyms);
3209 NO_SPACE(symbol_destructor);
3211 symbol_type_tag = CALLOC(sizeof(char *), nsyms);
3212 NO_SPACE(symbol_type_tag);
3216 v = TMALLOC(bucket *, nsyms);
3220 v[start_symbol] = 0;
3223 j = (Value_t)(start_symbol + 1);
3224 for (bp = first_symbol; bp; bp = bp->next)
3226 if (bp->class == TERM)
3231 assert(i == ntokens && j == nsyms);
3233 for (i = 1; i < ntokens; ++i)
3236 goal->index = (Index_t)(start_symbol + 1);
3237 k = (Value_t)(start_symbol + 2);
3247 for (i = (Value_t)(start_symbol + 1); i < nsyms; ++i)
3257 for (i = 1; i < ntokens; ++i)
3262 for (j = k++; j > 0 && symbol_value[j - 1] > n; --j)
3263 symbol_value[j] = symbol_value[j - 1];
3264 symbol_value[j] = n;
3270 if (v[1]->value == UNDEFINED)
3275 for (i = 2; i < ntokens; ++i)
3277 if (v[i]->value == UNDEFINED)
3279 while (j < k && n == symbol_value[j])
3281 while (++j < k && n == symbol_value[j])
3290 symbol_name[0] = name_pool + 8;
3291 symbol_value[0] = 0;
3293 symbol_assoc[0] = TOKEN;
3294 #if defined(YYBTYACC)
3298 for (i = 1; i < ntokens; ++i)
3300 symbol_name[i] = v[i]->name;
3301 symbol_value[i] = v[i]->value;
3302 symbol_prec[i] = v[i]->prec;
3303 symbol_assoc[i] = v[i]->assoc;
3304 #if defined(YYBTYACC)
3305 symbol_pval[i] = v[i]->value;
3306 if (symbol_pval[i] > max_tok_pval)
3307 max_tok_pval = symbol_pval[i];
3310 symbol_destructor[i] = v[i]->destructor;
3311 symbol_type_tag[i] = v[i]->tag;
3315 symbol_name[start_symbol] = name_pool;
3316 symbol_value[start_symbol] = -1;
3317 symbol_prec[start_symbol] = 0;
3318 symbol_assoc[start_symbol] = TOKEN;
3319 #if defined(YYBTYACC)
3320 symbol_pval[start_symbol] = (Value_t)(max_tok_pval + 1);
3322 for (++i; i < nsyms; ++i)
3325 symbol_name[k] = v[i]->name;
3326 symbol_value[k] = v[i]->value;
3327 symbol_prec[k] = v[i]->prec;
3328 symbol_assoc[k] = v[i]->assoc;
3329 #if defined(YYBTYACC)
3330 symbol_pval[k] = (Value_t)((max_tok_pval + 1) + v[i]->value + 1);
3333 symbol_destructor[k] = v[i]->destructor;
3334 symbol_type_tag[k] = v[i]->tag;
3341 symbol_pname = TMALLOC(char *, nsyms);
3342 NO_SPACE(symbol_pname);
3344 for (i = 0; i < nsyms; ++i)
3345 protect_string(symbol_name[i], &(symbol_pname[i]));
3359 ritem = TMALLOC(Value_t, nitems);
3362 rlhs = TMALLOC(Value_t, nrules);
3365 rrhs = TMALLOC(Value_t, nrules + 1);
3368 rprec = TREALLOC(Value_t, rprec, nrules);
3371 rassoc = TREALLOC(Assoc_t, rassoc, nrules);
3375 ritem[1] = goal->index;
3380 rlhs[2] = start_symbol;
3386 for (i = 3; i < nrules; ++i)
3388 #if defined(YYBTYACC)
3389 if (plhs[i]->args > 0)
3391 if (plhs[i]->argnames)
3393 FREE(plhs[i]->argnames);
3394 plhs[i]->argnames = NULL;
3396 if (plhs[i]->argtags)
3398 FREE(plhs[i]->argtags);
3399 plhs[i]->argtags = NULL;
3402 #endif /* defined(YYBTYACC) */
3403 rlhs[i] = plhs[i]->index;
3409 ritem[j] = pitem[j]->index;
3410 if (pitem[j]->class == TERM)
3412 prec2 = pitem[j]->prec;
3413 assoc = pitem[j]->assoc;
3417 ritem[j] = (Value_t)-i;
3419 if (rprec[i] == UNDEFINED)
3429 #if defined(YYBTYACC)
3438 size_t j, spacing = 0;
3439 FILE *f = verbose_file;
3445 for (i = 2; i < nrules; ++i)
3447 if (rlhs[i] != rlhs[i - 1])
3451 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
3452 spacing = strlen(symbol_name[rlhs[i]]) + 1;
3456 fprintf(f, "%4d ", i - 2);
3463 while (ritem[k] >= 0)
3465 fprintf(f, " %s", symbol_name[ritem[k]]);
3473 #if defined(YYBTYACC)
3475 finalize_destructors(void)
3481 for (i = 2; i < nsyms; ++i)
3483 tag = symbol_type_tag[i];
3484 if (symbol_destructor[i] == NULL)
3487 { /* use <> destructor, if there is one */
3488 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3490 symbol_destructor[i] = TMALLOC(char,
3491 strlen(bp->destructor) + 1);
3492 NO_SPACE(symbol_destructor[i]);
3493 strcpy(symbol_destructor[i], bp->destructor);
3497 { /* use type destructor for this tag, if there is one */
3498 bp = lookup_type_destructor(tag);
3499 if (bp->destructor != NULL)
3501 symbol_destructor[i] = TMALLOC(char,
3502 strlen(bp->destructor) + 1);
3503 NO_SPACE(symbol_destructor[i]);
3504 strcpy(symbol_destructor[i], bp->destructor);
3507 { /* use <*> destructor, if there is one */
3508 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3509 /* replace "$$" with "(*val).tag" in destructor code */
3510 symbol_destructor[i]
3511 = process_destructor_XX(bp->destructor, tag);
3516 { /* replace "$$" with "(*val)[.tag]" in destructor code */
3517 symbol_destructor[i]
3518 = process_destructor_XX(symbol_destructor[i], tag);
3521 /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */
3522 DO_FREE(symbol_type_tag); /* no longer needed */
3523 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3526 /* 'bp->tag' is a static value, don't free */
3527 FREE(bp->destructor);
3530 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3533 /* 'bp->tag' is a static value, don't free */
3534 FREE(bp->destructor);
3537 if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL)
3544 /* 'bp->tag' freed by 'free_tags()' */
3545 FREE(bp->destructor);
3550 #endif /* defined(YYBTYACC) */
3555 write_section(code_file, banner);
3556 create_symbol_table();
3557 read_declarations();
3559 free_symbol_table();
3566 #if defined(YYBTYACC)
3568 finalize_destructors();
3575 free_declarations(param *list)
3579 param *next = list->next;
3592 lex_param = free_declarations(lex_param);
3593 parse_param = free_declarations(parse_param);
3603 DO_FREE(symbol_name);
3604 DO_FREE(symbol_prec);
3605 DO_FREE(symbol_assoc);
3606 DO_FREE(symbol_value);
3607 #if defined(YYBTYACC)
3608 DO_FREE(symbol_pval);
3609 DO_FREE(symbol_destructor);
3610 DO_FREE(symbol_type_tag);