1 /* $Id: reader.c,v 1.68 2017/02/02 01:05:36 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_initial_action(void);
26 static void copy_destructor(void);
27 static char *process_destructor_XX(char *code, char *tag);
30 #define CACHE_SIZE 256
32 static int cinc, cache_size;
35 static int tagmax, havetags;
36 static char **tag_table;
46 static char last_was_action;
48 static int trialaction;
52 static bucket **pitem;
57 static size_t name_pool_size;
58 static char *name_pool;
60 char line_format[] = "#line %d \"%s\"\n";
66 int destructor = 0; /* =1 if at least one %destructor */
68 static bucket *default_destructor[3] =
71 #define UNTYPED_DEFAULT 0
72 #define TYPED_DEFAULT 1
73 #define TYPE_SPECIFIED 2
76 lookup_type_destructor(char *tag)
78 const char fmt[] = "%.*s destructor";
79 char name[1024] = "\0";
80 bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED];
82 while ((bp = *bpp) != NULL)
89 sprintf(name, fmt, (int)(sizeof(name) - sizeof(fmt)), tag);
90 *bpp = bp = make_bucket(name);
95 #endif /* defined(YYBTYACC) */
101 if (cinc >= cache_size)
103 cache_size += CACHE_SIZE;
104 cache = TREALLOC(char, cache, cache_size);
107 cache[cinc] = (char)c;
126 * Expect this pattern:
127 * /^[[:space:]]*#[[:space:]]*
130 * ([[:space:]]*|[[:space:]]+"[^"]+")/
135 #define UNLESS(what) if (what) { ld = ldERR; break; }
140 LINE_DIR ld = ldSPC1;
141 for (n = 0; (ld <= ldOK) && (line[n] != '\0'); ++n)
143 int ch = UCH(line[n]);
162 UNLESS(strncmp(line + n, "line", 4));
170 UNLESS(!isspace(UCH(line[n])));
179 UNLESS(!isdigit(ch));
189 UNLESS(!isspace(ch));
199 UNLESS(line[n + 1] == '"');
219 size_t need = (size_t) (name_end - name_1st);
220 if (need > input_file_name_len)
222 input_file_name_len = need;
223 input_file_name = TREALLOC(char, input_file_name, need + 1);
224 NO_SPACE(input_file_name);
226 memcpy(input_file_name, line + name_1st + 1, need - 1);
227 input_file_name[need - 1] = '\0';
230 if (ld >= ldNUM && ld < ldERR)
232 lineno = (int)strtol(line + line_1st, NULL, 10) - 1;
242 FILE *f = input_file;
248 if (saw_eof || (c = getc(f)) == EOF)
260 if (line == NULL || linesize != (LINESIZE + 1))
264 linesize = LINESIZE + 1;
265 line = TMALLOC(char, linesize);
276 if ((i + 3) >= linesize)
278 linesize += LINESIZE;
279 line = TREALLOC(char, line, linesize);
292 while (line_directive());
307 p = TMALLOC(char, s - line + 1);
312 while ((*t++ = *s++) != '\n')
323 a.a_line = dup_line();
324 a.a_cptr = a.a_line + (cptr - line);
329 if (*s == '*' && s[1] == '/')
339 unterminated_comment(&a);
372 else if (s[1] == '/')
397 switch (ch = next_inline())
424 static struct keyword
430 { "binary", NONASSOC },
431 { "debug", XXXDEBUG },
432 #if defined(YYBTYACC)
433 { "destructor", DESTRUCTOR },
435 { "error-verbose",ERROR_VERBOSE },
436 { "expect", EXPECT },
437 { "expect-rr", EXPECT_RR },
439 #if defined(YYBTYACC)
440 { "initial-action", INITIAL_ACTION },
443 { "lex-param", LEX_PARAM },
444 #if defined(YYBTYACC)
445 { "locations", LOCATIONS },
447 { "nonassoc", NONASSOC },
448 { "parse-param", PARSE_PARAM },
449 { "pure-parser", PURE_PARSER },
454 { "token-table", TOKEN_TABLE },
457 { "yacc", POSIX_YACC },
462 compare_keys(const void *a, const void *b)
464 const struct keyword *p = (const struct keyword *)a;
465 const struct keyword *q = (const struct keyword *)b;
466 return strcmp(p->name, q->name);
497 /* treat keywords spelled with '_' as if it were '-' */
508 if ((key = bsearch(cache, keywords,
509 sizeof(keywords) / sizeof(*key),
510 sizeof(*key), compare_keys)))
518 if (c == '%' || c == '\\')
529 syntax_error(lineno, line, t_cptr);
537 FILE *f = output_file;
543 syntax_error(lineno, line, cptr);
545 fprintf(f, "#ident \"");
565 copy_string(int quote)
567 struct mstring *temp = msnew();
571 a.a_line = dup_line();
572 a.a_cptr = a.a_line + (cptr - line - 1);
584 unterminated_string(&a);
593 unterminated_string(&a);
602 struct mstring *temp = msnew();
609 while ((c = *++cptr) != '\n')
612 if (c == '*' && cptr[1] == '/')
622 a.a_line = dup_line();
623 a.a_cptr = a.a_line + (cptr - line - 1);
631 if (c == '*' && *cptr == '/')
642 unterminated_comment(&a);
654 int need_newline = 0;
657 a.a_line = dup_line();
658 a.a_cptr = a.a_line + (cptr - line - 2);
664 unterminated_text(&a);
667 fprintf(f, line_format, lineno, input_file_name);
679 unterminated_text(&a);
685 char *s = copy_string(c);
695 char *s = copy_comment();
722 puts_both(const char *s)
726 fputs(s, union_file);
744 a.a_line = dup_line();
745 a.a_cptr = a.a_line + (cptr - line - 6);
748 over_unionized(cptr - 6);
751 puts_both("#ifdef YYSTYPE\n");
752 puts_both("#undef YYSTYPE_IS_DECLARED\n");
753 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
754 puts_both("#endif\n");
755 puts_both("#ifndef YYSTYPE_IS_DECLARED\n");
756 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
759 fprintf(text_file, line_format, lineno, input_file_name);
760 puts_both("typedef union");
771 unterminated_union(&a);
781 puts_both(" YYSTYPE;\n");
782 puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n");
791 char *s = copy_string(c);
799 char *s = copy_comment();
811 after_blanks(char *s)
813 while (*s != '\0' && isspace(UCH(*s)))
819 * Trim leading/trailing blanks, and collapse multiple embedded blanks to a
820 * single space. Return index to last character in the buffer.
823 trim_blanks(char *buffer)
828 char *s = after_blanks(d);
830 while ((*d++ = *s++) != '\0')
836 while ((--d != buffer) && isspace(UCH(*d)))
839 for (s = d = buffer; (*d++ = *s++) != '\0';)
841 if (isspace(UCH(*s)))
844 while (isspace(UCH(*s)))
853 return (int)strlen(buffer) - 1;
857 * Scan forward in the current line-buffer looking for a right-curly bracket.
859 * Parameters begin with a left-curly bracket, and continue until there are no
860 * more interesting characters after the last right-curly bracket on the
861 * current line. Bison documents parameters as separated like this:
862 * {type param1} {type2 param2}
863 * but also accepts commas (although some versions of bison mishandle this)
864 * {type param1, type2 param2}
874 switch (next_inline())
893 save_param(int k, char *buffer, int name, int type2)
897 p = TMALLOC(param, 1);
900 p->type2 = strdup(buffer + type2);
902 buffer[type2] = '\0';
903 (void)trim_blanks(p->type2);
905 p->name = strdup(buffer + name);
908 (void)trim_blanks(p->name);
910 p->type = strdup(buffer);
912 (void)trim_blanks(p->type);
936 * Keep a linked list of parameters. This may be multi-line, if the trailing
937 * right-curly bracket is absent.
948 int st_lineno = lineno;
982 if ((curly == 1) && (cptr == line))
992 if (curly == 0 && !isspace(UCH(c)))
1000 buf_size = (size_t) linesize;
1001 buf = TMALLOC(char, buf_size);
1009 buf_size += (size_t) linesize;
1010 buf = TREALLOC(char, buf, buf_size);
1015 if ((state == 2) && (c == L_CURL))
1019 else if ((state == 2) && isspace(UCH(c)))
1023 else if ((c != L_CURL) && (c != R_CURL))
1030 while (curly < 2 || more_curly());
1043 (void)trim_blanks(buf);
1048 char *parms = (comma + 1);
1049 comma = strchr(parms, ',');
1053 (void)trim_blanks(parms);
1054 i = (int)strlen(parms) - 1;
1060 if (parms[i] == ']')
1063 while (i >= 0 && level > 0 && parms[i] != '[')
1065 if (parms[i] == ']')
1067 else if (parms[i] == '[')
1080 while (i > 0 && (isalnum(UCH(parms[i])) || UCH(parms[i]) == '_'))
1083 if (!isspace(UCH(parms[i])) && parms[i] != '*')
1088 save_param(k, parms, name, type2);
1096 syntax_error(lineno, line, cptr);
1102 if (c >= '0' && c <= '9')
1104 if (c >= 'A' && c <= 'F')
1105 return (c - 'A' + 10);
1106 if (c >= 'a' && c <= 'f')
1107 return (c - 'a' + 10);
1120 a.a_lineno = lineno;
1121 a.a_line = dup_line();
1122 a.a_cptr = a.a_line + (cptr - line);
1132 unterminated_string(&a);
1135 char *c_cptr = cptr - 1;
1143 unterminated_string(&a);
1158 n = (n << 3) + (c - '0');
1162 n = (n << 3) + (c - '0');
1167 illegal_character(c_cptr);
1174 if (n < 0 || n >= 16)
1175 illegal_character(c_cptr);
1180 if (i < 0 || i >= 16)
1185 illegal_character(c_cptr);
1218 s = TMALLOC(char, n);
1221 for (i = 0; i < n; ++i)
1230 for (i = 0; i < n; ++i)
1233 if (c == '\\' || c == cache[0])
1238 else if (isprint(c))
1267 cachec(((c >> 6) & 7) + '0');
1268 cachec(((c >> 3) & 7) + '0');
1269 cachec((c & 7) + '0');
1283 if (n == 1 && bp->value == UNDEFINED)
1284 bp->value = UCH(*s);
1291 is_reserved(char *name)
1295 if (strcmp(name, ".") == 0 ||
1296 strcmp(name, "$accept") == 0 ||
1297 strcmp(name, "$end") == 0)
1300 if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2])))
1303 while (isdigit(UCH(*s)))
1318 for (c = *cptr; IS_IDENT(c); c = *++cptr)
1322 if (is_reserved(cache))
1323 used_reserved(cache);
1325 return (lookup(cache));
1335 for (c = *cptr; isdigit(c); c = *++cptr)
1336 n = (Value_t)(10 * n + (c - '0'));
1342 cache_tag(char *tag, size_t len)
1347 for (i = 0; i < ntags; ++i)
1349 if (strncmp(tag, tag_table[i], len) == 0 &&
1350 tag_table[i][len] == NUL)
1351 return (tag_table[i]);
1354 if (ntags >= tagmax)
1359 ? TREALLOC(char *, tag_table, tagmax)
1360 : TMALLOC(char *, tagmax));
1361 NO_SPACE(tag_table);
1364 s = TMALLOC(char, len + 1);
1367 strncpy(s, tag, len);
1369 tag_table[ntags++] = s;
1377 int t_lineno = lineno;
1378 char *t_line = dup_line();
1379 char *t_cptr = t_line + (cptr - line);
1385 if (!isalpha(c) && c != '_' && c != '$')
1386 illegal_tag(t_lineno, t_line, t_cptr);
1394 while (IS_IDENT(c));
1401 illegal_tag(t_lineno, t_line, t_cptr);
1406 return cache_tag(cache, (size_t) cinc);
1409 #if defined(YYBTYACC)
1415 while (isalnum(UCH(*cptr)) || *cptr == '_' || *cptr == '$')
1417 return cache_tag(b, (size_t) (cptr - b));
1422 declare_tokens(int assoc)
1445 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1447 else if (c == '\'' || c == '"')
1453 tokenized_start(bp->name);
1458 if (bp->tag && tag != bp->tag)
1459 retyped_warning(bp->name);
1465 if (bp->prec && prec != bp->prec)
1466 reprec_warning(bp->name);
1467 bp->assoc = (Assoc_t)assoc;
1478 value = get_number();
1479 if (bp->value != UNDEFINED && value != bp->value)
1480 revalued_warning(bp->name);
1490 * %expect requires special handling
1491 * as it really isn't part of the yacc
1492 * grammar only a flag for yacc proper.
1495 declare_expect(int assoc)
1499 if (assoc != EXPECT && assoc != EXPECT_RR)
1503 * Stay away from nextc - doesn't
1504 * detect EOL and will read to EOF.
1514 if (assoc == EXPECT)
1515 SRexpect = get_number();
1517 RRexpect = get_number();
1521 * Looking for number before EOL.
1522 * Spaces, tabs, and numbers are ok,
1523 * words, punc., etc. are syntax errors.
1525 else if (c == '\n' || isalpha(c) || !isspace(c))
1527 syntax_error(lineno, line, cptr);
1538 #if defined(YYBTYACC)
1540 declare_argtypes(bucket *bp)
1542 char *tags[MAXARGS];
1546 retyped_warning(bp->name);
1547 cptr++; /* skip open paren */
1554 syntax_error(lineno, line, cptr);
1555 tags[args++] = get_tag();
1562 cptr++; /* skip close paren */
1564 bp->argnames = TMALLOC(char *, args);
1565 NO_SPACE(bp->argnames);
1566 bp->argtags = CALLOC(sizeof(char *), args + 1);
1567 NO_SPACE(bp->argtags);
1570 bp->argtags[args] = tags[args];
1571 bp->argnames[args] = NULL;
1594 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1597 #if defined(YYBTYACC)
1598 if (nextc() == L_PAREN)
1599 declare_argtypes(bp);
1604 else if (c == '\'' || c == '"')
1607 #if defined(YYBTYACC)
1616 if (bp->tag && tag != bp->tag)
1617 retyped_warning(bp->name);
1632 if (!isalpha(c) && c != '_' && c != '.' && c != '$')
1633 syntax_error(lineno, line, cptr);
1635 if (bp->class == TERM)
1636 terminal_start(bp->name);
1637 if (goal && goal != bp)
1638 restarted_warning();
1643 read_declarations(void)
1647 cache_size = CACHE_SIZE;
1648 cache = TMALLOC(char, cache_size);
1657 syntax_error(lineno, line, cptr);
1658 switch (k = keyword())
1712 #if defined(YYBTYACC)
1721 case INITIAL_ACTION:
1722 copy_initial_action();
1731 /* noop for bison compatibility. byacc is already designed to be posix
1732 * yacc compatible. */
1739 initialize_grammar(void)
1744 pitem = TMALLOC(bucket *, maxitems);
1755 plhs = TMALLOC(bucket *, maxrules);
1762 rprec = TMALLOC(Value_t, maxrules);
1769 rassoc = TMALLOC(Assoc_t, maxrules);
1781 pitem = TREALLOC(bucket *, pitem, maxitems);
1790 plhs = TREALLOC(bucket *, plhs, maxrules);
1793 rprec = TREALLOC(Value_t, rprec, maxrules);
1796 rassoc = TREALLOC(Assoc_t, rassoc, maxrules);
1800 /* set immediately prior to where copy_args() could be called, and incremented by
1801 the various routines that will rescan the argument list as appropriate */
1802 static int rescan_lineno;
1803 #if defined(YYBTYACC)
1806 copy_args(int *alen)
1808 struct mstring *s = msnew();
1809 int depth = 0, len = 1;
1813 a.a_lineno = lineno;
1814 a.a_line = dup_line();
1815 a.a_cptr = a.a_line + (cptr - line - 1);
1817 while ((c = *cptr++) != R_PAREN || depth || quote)
1819 if (c == ',' && !quote && !depth)
1832 unterminated_string(&a);
1834 unterminated_arglist(&a);
1851 else if (c == R_PAREN)
1853 else if (c == '\"' || c == '\'')
1864 parse_id(char *p, char **save)
1868 while (isspace(UCH(*p)))
1871 if (!isalpha(UCH(*p)) && *p != '_')
1874 while (isalnum(UCH(*p)) || *p == '_' || *p == '$')
1878 *save = cache_tag(b, (size_t) (p - b));
1884 parse_int(char *p, int *save)
1886 int neg = 0, val = 0;
1888 while (isspace(UCH(*p)))
1896 if (!isdigit(UCH(*p)))
1898 while (isdigit(UCH(*p)))
1899 val = val * 10 + *p++ - '0';
1908 parse_arginfo(bucket *a, char *args, int argslen)
1910 char *p = args, *tmp;
1915 if (a->args != argslen)
1916 arg_number_disagree_warning(rescan_lineno, a->name);
1921 if ((a->args = argslen) == 0)
1923 a->argnames = TMALLOC(char *, argslen);
1924 NO_SPACE(a->argnames);
1925 a->argtags = TMALLOC(char *, argslen);
1926 NO_SPACE(a->argtags);
1930 for (i = 0; i < argslen; i++)
1932 while (isspace(UCH(*p)))
1937 while (isspace(UCH(*p)))
1943 if (!(p = parse_id(p + 1, &tmp)))
1945 while (isspace(UCH(*p)))
1952 if (a->argtags[i] != tmp)
1953 arg_type_disagree_warning(rescan_lineno, i + 1, a->name);
1956 a->argtags[i] = tmp;
1959 a->argtags[i] = NULL;
1960 if (!(p = parse_id(p, &a->argnames[i])))
1962 while (isspace(UCH(*p)))
1972 compile_arg(char **theptr, char *yyvaltag)
1975 struct mstring *c = msnew();
1977 Value_t *offsets = NULL, maxoffset;
1982 for (i = nitems - 1; pitem[i]; --i)
1985 if (pitem[i]->class != ARGUMENT)
1990 offsets = TMALLOC(Value_t, maxoffset + 1);
1993 for (j = 0, i++; i < nitems; i++)
1994 if (pitem[i]->class != ARGUMENT)
1995 offsets[++j] = (Value_t)(i - nitems + 1);
1997 rhs = pitem + nitems - 1;
2000 msprintf(c, "yyval.%s = ", yyvaltag);
2002 msprintf(c, "yyval = ");
2009 if (!(p = parse_id(++p, &tag)) || *p++ != '>')
2010 illegal_tag(rescan_lineno, NULL, NULL);
2011 if (isdigit(UCH(*p)) || *p == '-')
2014 if (!(p = parse_int(p, &val)))
2015 dollar_error(rescan_lineno, NULL, NULL);
2018 else if (val > maxoffset)
2020 dollar_warning(rescan_lineno, val);
2021 i = val - maxoffset;
2023 else if (maxoffset > 0)
2026 if (!tag && !(tag = rhs[i]->tag) && havetags)
2027 untyped_rhs(val, rhs[i]->name);
2029 msprintf(c, "yystack.l_mark[%d]", i);
2031 msprintf(c, ".%s", tag);
2035 else if (isalpha(UCH(*p)) || *p == '_')
2038 if (!(p = parse_id(p, &arg)))
2039 dollar_error(rescan_lineno, NULL, NULL);
2040 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2041 if (arg == plhs[nrules]->argnames[i])
2044 unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL);
2046 tag = plhs[nrules]->argtags[i];
2047 msprintf(c, "yystack.l_mark[%d]",
2048 i - plhs[nrules]->args + 1 - n);
2050 msprintf(c, ".%s", tag);
2052 untyped_arg_warning(rescan_lineno, "$", arg);
2055 dollar_error(rescan_lineno, NULL, NULL);
2059 at_error(rescan_lineno, NULL, NULL);
2075 can_elide_arg(char **theptr, char *yyvaltag)
2080 Value_t *offsets = NULL, maxoffset = 0;
2088 if (!(p = parse_id(++p, &tag)) || *p++ != '>')
2091 for (i = nitems - 1; pitem[i]; --i)
2094 if (pitem[i]->class != ARGUMENT)
2099 offsets = TMALLOC(Value_t, maxoffset + 1);
2102 for (j = 0, i++; i < nitems; i++)
2103 if (pitem[i]->class != ARGUMENT)
2104 offsets[++j] = (Value_t)(i - nitems + 1);
2106 rhs = pitem + nitems - 1;
2108 if (isdigit(UCH(*p)) || *p == '-')
2111 if (!(p = parse_int(p, &val)))
2117 else if (val > maxoffset)
2128 else if (isalpha(UCH(*p)) || *p == '_')
2131 if (!(p = parse_id(p, &arg)))
2133 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2134 if (arg == plhs[nrules]->argnames[i])
2139 tag = plhs[nrules]->argtags[i];
2140 rv = plhs[nrules]->args + n - i;
2143 if (tag && yyvaltag)
2145 if (strcmp(tag, yyvaltag))
2148 else if (tag || yyvaltag)
2158 #define ARG_CACHE_SIZE 1024
2159 static struct arg_cache
2161 struct arg_cache *next;
2165 *arg_cache[ARG_CACHE_SIZE];
2168 lookup_arg_cache(char *code)
2170 struct arg_cache *entry;
2172 entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE];
2175 if (!strnscmp(entry->code, code))
2177 entry = entry->next;
2183 insert_arg_cache(char *code, int rule)
2185 struct arg_cache *entry = NEW(struct arg_cache);
2189 i = strnshash(code) % ARG_CACHE_SIZE;
2192 entry->next = arg_cache[i];
2193 arg_cache[i] = entry;
2197 clean_arg_cache(void)
2199 struct arg_cache *e, *t;
2202 for (i = 0; i < ARG_CACHE_SIZE; i++)
2204 for (e = arg_cache[i]; (t = e); e = e->next, FREE(t))
2206 arg_cache[i] = NULL;
2209 #endif /* defined(YYBTYACC) */
2212 advance_to_start(void)
2218 #if defined(YYBTYACC)
2243 syntax_error(lineno, line, s_cptr);
2248 if (!isalpha(c) && c != '_' && c != '.' && c != '_')
2249 syntax_error(lineno, line, cptr);
2253 if (bp->class == TERM)
2254 terminal_start(bp->name);
2262 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2263 #if defined(YYBTYACC)
2267 args = copy_args(&argslen);
2273 syntax_error(lineno, line, cptr);
2274 start_rule(bp, s_lineno);
2275 #if defined(YYBTYACC)
2276 parse_arginfo(bp, args, argslen);
2282 start_rule(bucket *bp, int s_lineno)
2284 if (bp->class == TERM)
2285 terminal_lhs(s_lineno);
2286 bp->class = NONTERM;
2289 if (nrules >= maxrules)
2292 rprec[nrules] = UNDEFINED;
2293 rassoc[nrules] = TOKEN;
2301 if (!last_was_action && plhs[nrules]->tag)
2303 if (pitem[nitems - 1])
2305 for (i = nitems - 1; (i > 0) && pitem[i]; --i)
2307 if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag)
2308 default_action_warning(plhs[nrules]->name);
2311 default_action_warning(plhs[nrules]->name);
2314 last_was_action = 0;
2315 if (nitems >= maxitems)
2323 insert_empty_rule(void)
2328 assert(cache_size >= CACHE_SIZE);
2329 sprintf(cache, "$$%d", ++gensym);
2330 bp = make_bucket(cache);
2331 last_symbol->next = bp;
2333 bp->tag = plhs[nrules]->tag;
2335 #if defined(YYBTYACC)
2339 nitems = (Value_t)(nitems + 2);
2340 if (nitems > maxitems)
2342 bpp = pitem + nitems - 1;
2344 while ((bpp[0] = bpp[-1]) != 0)
2347 if (++nrules >= maxrules)
2349 plhs[nrules] = plhs[nrules - 1];
2350 plhs[nrules - 1] = bp;
2351 rprec[nrules] = rprec[nrules - 1];
2352 rprec[nrules - 1] = 0;
2353 rassoc[nrules] = rassoc[nrules - 1];
2354 rassoc[nrules - 1] = TOKEN;
2357 #if defined(YYBTYACC)
2359 insert_arg_rule(char *arg, char *tag)
2361 int line_number = rescan_lineno;
2362 char *code = compile_arg(&arg, tag);
2363 int rule = lookup_arg_cache(code);
2364 FILE *f = action_file;
2369 insert_arg_cache(code, rule);
2370 trialaction = 1; /* arg rules always run in trial mode */
2371 fprintf(f, "case %d:\n", rule - 2);
2373 fprintf(f, line_format, line_number, input_file_name);
2374 fprintf(f, "%s;\n", code);
2375 fprintf(f, "break;\n");
2376 insert_empty_rule();
2377 plhs[rule]->tag = cache_tag(tag, strlen(tag));
2378 plhs[rule]->class = ARGUMENT;
2382 if (++nitems > maxitems)
2384 pitem[nitems - 1] = plhs[rule];
2396 int s_lineno = lineno;
2397 #if defined(YYBTYACC)
2403 if (c == '\'' || c == '"')
2409 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2410 #if defined(YYBTYACC)
2414 args = copy_args(&argslen);
2422 start_rule(bp, s_lineno);
2423 #if defined(YYBTYACC)
2424 parse_arginfo(bp, args, argslen);
2430 if (last_was_action)
2431 insert_empty_rule();
2432 last_was_action = 0;
2434 #if defined(YYBTYACC)
2437 if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL)
2440 if (plhs[nrules]->args != bp->args)
2441 wrong_number_args_warning("default ", bp->name);
2442 for (i = bp->args - 1; i >= 0; i--)
2443 if (plhs[nrules]->argtags[i] != bp->argtags[i])
2444 wrong_type_for_arg_warning(i + 1, bp->name);
2446 else if (bp->args != argslen)
2447 wrong_number_args_warning("", bp->name);
2452 int elide_cnt = can_elide_arg(&ap, bp->argtags[0]);
2454 if (elide_cnt > argslen)
2458 for (i = 1; i < elide_cnt; i++)
2459 if (can_elide_arg(&ap, bp->argtags[i]) != elide_cnt - i)
2467 assert(i == elide_cnt);
2474 for (; i < argslen; i++)
2475 ap = insert_arg_rule(ap, bp->argtags[i]);
2478 #endif /* defined(YYBTYACC) */
2480 if (++nitems > maxitems)
2482 pitem[nitems - 1] = bp;
2491 #if defined(YYBTYACC)
2495 FILE *f = action_file;
2497 Value_t *offsets = NULL, maxoffset;
2500 a.a_lineno = lineno;
2501 a.a_line = dup_line();
2502 a.a_cptr = a.a_line + (cptr - line);
2504 if (last_was_action)
2505 insert_empty_rule();
2506 last_was_action = 1;
2507 #if defined(YYBTYACC)
2508 trialaction = (*cptr == L_BRAC);
2511 fprintf(f, "case %d:\n", nrules - 2);
2512 #if defined(YYBTYACC)
2516 fprintf(f, " if (!yytrial)\n");
2520 fprintf(f, line_format, lineno, input_file_name);
2524 /* avoid putting curly-braces in first column, to ease editing */
2525 if (*after_blanks(cptr) == L_CURL)
2528 cptr = after_blanks(cptr);
2533 for (i = nitems - 1; pitem[i]; --i)
2536 if (pitem[i]->class != ARGUMENT)
2541 offsets = TMALLOC(Value_t, maxoffset + 1);
2544 for (j = 0, i++; i < nitems; i++)
2546 if (pitem[i]->class != ARGUMENT)
2548 offsets[++j] = (Value_t)(i - nitems + 1);
2552 rhs = pitem + nitems - 1;
2561 int d_lineno = lineno;
2562 char *d_line = dup_line();
2563 char *d_cptr = d_line + (cptr - line);
2570 fprintf(f, "yyval.%s", tag);
2575 else if (isdigit(c))
2579 fprintf(f, "yystack.l_mark[%d].%s", -n, tag);
2580 else if (i > maxoffset)
2582 dollar_warning(d_lineno, i);
2583 fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag);
2586 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2590 else if (c == '-' && isdigit(UCH(cptr[1])))
2593 i = -get_number() - n;
2594 fprintf(f, "yystack.l_mark[%d].%s", i, tag);
2598 #if defined(YYBTYACC)
2599 else if (isalpha(c) || c == '_')
2601 char *arg = scan_id();
2602 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2603 if (arg == plhs[nrules]->argnames[i])
2606 unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr);
2607 fprintf(f, "yystack.l_mark[%d].%s",
2608 i - plhs[nrules]->args + 1 - n, tag);
2614 dollar_error(d_lineno, d_line, d_cptr);
2616 else if (cptr[1] == '$')
2620 tag = plhs[nrules]->tag;
2623 fprintf(f, "yyval.%s", tag);
2626 fprintf(f, "yyval");
2628 #if defined(YYBTYACC)
2633 else if (isdigit(UCH(cptr[1])))
2637 if (havetags && offsets)
2639 if (i <= 0 || i > maxoffset)
2641 tag = rhs[offsets[i]]->tag;
2643 untyped_rhs(i, rhs[offsets[i]]->name);
2644 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2649 fprintf(f, "yystack.l_mark[%d]", -n);
2650 else if (i > maxoffset)
2652 dollar_warning(lineno, i);
2653 fprintf(f, "yystack.l_mark[%d]", i - maxoffset);
2656 fprintf(f, "yystack.l_mark[%d]", offsets[i]);
2660 else if (cptr[1] == '-')
2666 fprintf(f, "yystack.l_mark[%d]", -i - n);
2669 #if defined(YYBTYACC)
2670 else if (isalpha(UCH(cptr[1])) || cptr[1] == '_')
2675 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2676 if (arg == plhs[nrules]->argnames[i])
2679 unknown_arg_warning(lineno, "$", arg, line, cptr);
2680 tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]);
2681 fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n);
2683 fprintf(f, ".%s", tag);
2685 untyped_arg_warning(lineno, "$", arg);
2690 #if defined(YYBTYACC)
2695 int l_lineno = lineno;
2696 char *l_line = dup_line();
2697 char *l_cptr = l_line + (cptr - line);
2698 syntax_error(l_lineno, l_line, l_cptr);
2702 fprintf(f, "yyloc");
2706 else if (isdigit(UCH(cptr[1])))
2711 fprintf(f, "yystack.p_mark[%d]", -n);
2712 else if (i > maxoffset)
2714 at_warning(lineno, i);
2715 fprintf(f, "yystack.p_mark[%d]", i - maxoffset);
2718 fprintf(f, "yystack.p_mark[%d]", offsets[i]);
2721 else if (cptr[1] == '-')
2725 fprintf(f, "yystack.p_mark[%d]", -i - n);
2730 if (isalpha(c) || c == '_' || c == '$')
2737 while (isalnum(c) || c == '_' || c == '$');
2741 #if defined(YYBTYACC)
2744 if (trialaction && c == L_BRAC && depth == 0)
2750 if (trialaction && c == R_BRAC && depth == 1)
2755 if (c == L_BRAC && !haveyyval)
2759 if (c == L_CURL && !haveyyval)
2761 fprintf(f, " if (!yytrial)\n");
2763 fprintf(f, line_format, lineno, input_file_name);
2767 fprintf(f, "\nbreak;\n");
2782 unterminated_action(&a);
2787 fprintf(f, "\nbreak;\n");
2793 #if defined(YYBTYACC)
2812 #if defined(YYBTYACC)
2816 if (c == L_BRAC && !haveyyval)
2821 if (c == L_CURL && !haveyyval)
2823 fprintf(f, " if (!yytrial)\n");
2825 fprintf(f, line_format, lineno, input_file_name);
2830 fprintf(f, "\nbreak;\n");
2839 char *s = copy_string(c);
2847 char *s = copy_comment();
2858 #if defined(YYBTYACC)
2860 get_code(struct ainfo *a, const char *loc)
2865 struct mstring *code_mstr = msnew();
2868 msprintf(code_mstr, line_format, lineno, input_file_name);
2870 cptr = after_blanks(cptr);
2871 if (*cptr == L_CURL)
2872 /* avoid putting curly-braces in first column, to ease editing */
2873 mputc(code_mstr, '\t');
2875 syntax_error(lineno, line, cptr);
2877 a->a_lineno = lineno;
2878 a->a_line = dup_line();
2879 a->a_cptr = a->a_line + (cptr - line);
2888 int d_lineno = lineno;
2889 char *d_line = dup_line();
2890 char *d_cptr = d_line + (cptr - line);
2897 msprintf(code_mstr, "(*val).%s", tag);
2903 dollar_error(d_lineno, d_line, d_cptr);
2905 else if (cptr[1] == '$')
2907 /* process '$$' later; replacement is context dependent */
2908 msprintf(code_mstr, "$$");
2913 if (c == '@' && cptr[1] == '$')
2917 int l_lineno = lineno;
2918 char *l_line = dup_line();
2919 char *l_cptr = l_line + (cptr - line);
2920 syntax_error(l_lineno, l_line, l_cptr);
2922 msprintf(code_mstr, "%s", loc);
2926 if (isalpha(c) || c == '_' || c == '$')
2930 mputc(code_mstr, c);
2933 while (isalnum(c) || c == '_' || c == '$');
2937 mputc(code_mstr, c);
2944 unterminated_action(a);
2958 char *s = copy_string(c);
2959 msprintf(code_mstr, "%s", s);
2966 char *s = copy_comment();
2967 msprintf(code_mstr, "%s", s);
2976 return msdone(code_mstr);
2980 copy_initial_action(void)
2984 initial_action = get_code(&a, "yyloc");
2989 copy_destructor(void)
2996 code_text = get_code(&a, "(*loc)");
3006 { /* "no semantic type" default destructor */
3008 if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL)
3010 static char untyped_default[] = "<>";
3011 bp = make_bucket("untyped default");
3012 bp->tag = untyped_default;
3013 default_destructor[UNTYPED_DEFAULT] = bp;
3015 if (bp->destructor != NULL)
3016 destructor_redeclared_warning(&a);
3018 /* replace "$$" with "(*val)" in destructor code */
3019 bp->destructor = process_destructor_XX(code_text, NULL);
3021 else if (cptr[1] == '*' && cptr[2] == '>')
3022 { /* "no per-symbol or per-type" default destructor */
3024 if ((bp = default_destructor[TYPED_DEFAULT]) == NULL)
3026 static char typed_default[] = "<*>";
3027 bp = make_bucket("typed default");
3028 bp->tag = typed_default;
3029 default_destructor[TYPED_DEFAULT] = bp;
3031 if (bp->destructor != NULL)
3032 destructor_redeclared_warning(&a);
3035 /* postpone re-processing destructor $$s until end of grammar spec */
3036 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
3037 NO_SPACE(bp->destructor);
3038 strcpy(bp->destructor, code_text);
3042 { /* "semantic type" default destructor */
3043 char *tag = get_tag();
3044 bp = lookup_type_destructor(tag);
3045 if (bp->destructor != NULL)
3046 destructor_redeclared_warning(&a);
3048 /* replace "$$" with "(*val).tag" in destructor code */
3049 bp->destructor = process_destructor_XX(code_text, tag);
3052 else if (isalpha(c) || c == '_' || c == '.' || c == '$')
3053 { /* "symbol" destructor */
3055 if (bp->destructor != NULL)
3056 destructor_redeclared_warning(&a);
3059 /* postpone re-processing destructor $$s until end of grammar spec */
3060 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
3061 NO_SPACE(bp->destructor);
3062 strcpy(bp->destructor, code_text);
3073 process_destructor_XX(char *code, char *tag)
3078 struct mstring *new_code = msnew();
3079 char *codeptr = code;
3082 loop: /* step thru code */
3084 if (c == '$' && codeptr[1] == '$')
3088 msprintf(new_code, "(*val)");
3090 msprintf(new_code, "(*val).%s", tag);
3093 if (isalpha(c) || c == '_' || c == '$')
3100 while (isalnum(c) || c == '_' || c == '$');
3114 return msdone(new_code);
3142 if (c == '*' && *codeptr == '/')
3144 mputc(new_code, '/');
3156 #endif /* defined(YYBTYACC) */
3165 if (c == '%' || c == '\\')
3173 else if ((c == 'p' || c == 'P') &&
3174 ((c = cptr[2]) == 'r' || c == 'R') &&
3175 ((c = cptr[3]) == 'e' || c == 'E') &&
3176 ((c = cptr[4]) == 'c' || c == 'C') &&
3177 ((c = cptr[5], !IS_IDENT(c))))
3180 syntax_error(lineno, line, cptr);
3183 if (isalpha(c) || c == '_' || c == '.' || c == '$')
3185 else if (c == '\'' || c == '"')
3189 syntax_error(lineno, line, cptr);
3193 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
3196 rprec[nrules] = bp->prec;
3197 rassoc[nrules] = bp->assoc;
3206 initialize_grammar();
3221 #if defined(YYBTYACC)
3222 else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC))
3224 else if (c == L_CURL || c == '=')
3230 start_rule(plhs[nrules - 1], 0);
3239 syntax_error(lineno, line, cptr);
3242 #if defined(YYBTYACC)
3244 start_requires_args(goal->name);
3256 for (i = 0; i < ntags; ++i)
3258 assert(tag_table[i]);
3270 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
3271 for (bp = first_symbol; bp; bp = bp->next)
3272 name_pool_size += strlen(bp->name) + 1;
3274 name_pool = TMALLOC(char, name_pool_size);
3275 NO_SPACE(name_pool);
3277 strcpy(name_pool, "$accept");
3278 strcpy(name_pool + 8, "$end");
3280 for (bp = first_symbol; bp; bp = bp->next)
3284 while ((*t++ = *s++) != 0)
3296 if (goal->class == UNKNOWN)
3297 undefined_goal(goal->name);
3299 for (bp = first_symbol; bp; bp = bp->next)
3301 if (bp->class == UNKNOWN)
3303 undefined_symbol_warning(bp->name);
3310 protect_string(char *src, char **des)
3323 if ('\\' == *s || '"' == *s)
3329 *des = d = TMALLOC(char, len);
3335 if ('\\' == *s || '"' == *s)
3349 #if defined(YYBTYACC)
3350 Value_t max_tok_pval;
3355 for (bp = first_symbol; bp; bp = bp->next)
3358 if (bp->class == TERM)
3361 start_symbol = (Value_t)ntokens;
3362 nvars = (Value_t)(nsyms - ntokens);
3364 symbol_name = TMALLOC(char *, nsyms);
3365 NO_SPACE(symbol_name);
3367 symbol_value = TMALLOC(Value_t, nsyms);
3368 NO_SPACE(symbol_value);
3370 symbol_prec = TMALLOC(Value_t, nsyms);
3371 NO_SPACE(symbol_prec);
3373 symbol_assoc = TMALLOC(char, nsyms);
3374 NO_SPACE(symbol_assoc);
3376 #if defined(YYBTYACC)
3377 symbol_pval = TMALLOC(Value_t, nsyms);
3378 NO_SPACE(symbol_pval);
3382 symbol_destructor = CALLOC(sizeof(char *), nsyms);
3383 NO_SPACE(symbol_destructor);
3385 symbol_type_tag = CALLOC(sizeof(char *), nsyms);
3386 NO_SPACE(symbol_type_tag);
3390 v = TMALLOC(bucket *, nsyms);
3394 v[start_symbol] = 0;
3397 j = (Value_t)(start_symbol + 1);
3398 for (bp = first_symbol; bp; bp = bp->next)
3400 if (bp->class == TERM)
3405 assert(i == ntokens && j == nsyms);
3407 for (i = 1; i < ntokens; ++i)
3410 goal->index = (Index_t)(start_symbol + 1);
3411 k = (Value_t)(start_symbol + 2);
3421 for (i = (Value_t)(start_symbol + 1); i < nsyms; ++i)
3431 for (i = 1; i < ntokens; ++i)
3436 for (j = k++; j > 0 && symbol_value[j - 1] > n; --j)
3437 symbol_value[j] = symbol_value[j - 1];
3438 symbol_value[j] = n;
3444 if (v[1]->value == UNDEFINED)
3449 for (i = 2; i < ntokens; ++i)
3451 if (v[i]->value == UNDEFINED)
3453 while (j < k && n == symbol_value[j])
3455 while (++j < k && n == symbol_value[j])
3464 symbol_name[0] = name_pool + 8;
3465 symbol_value[0] = 0;
3467 symbol_assoc[0] = TOKEN;
3468 #if defined(YYBTYACC)
3472 for (i = 1; i < ntokens; ++i)
3474 symbol_name[i] = v[i]->name;
3475 symbol_value[i] = v[i]->value;
3476 symbol_prec[i] = v[i]->prec;
3477 symbol_assoc[i] = v[i]->assoc;
3478 #if defined(YYBTYACC)
3479 symbol_pval[i] = v[i]->value;
3480 if (symbol_pval[i] > max_tok_pval)
3481 max_tok_pval = symbol_pval[i];
3484 symbol_destructor[i] = v[i]->destructor;
3485 symbol_type_tag[i] = v[i]->tag;
3489 symbol_name[start_symbol] = name_pool;
3490 symbol_value[start_symbol] = -1;
3491 symbol_prec[start_symbol] = 0;
3492 symbol_assoc[start_symbol] = TOKEN;
3493 #if defined(YYBTYACC)
3494 symbol_pval[start_symbol] = (Value_t)(max_tok_pval + 1);
3496 for (++i; i < nsyms; ++i)
3499 symbol_name[k] = v[i]->name;
3500 symbol_value[k] = v[i]->value;
3501 symbol_prec[k] = v[i]->prec;
3502 symbol_assoc[k] = v[i]->assoc;
3503 #if defined(YYBTYACC)
3504 symbol_pval[k] = (Value_t)((max_tok_pval + 1) + v[i]->value + 1);
3507 symbol_destructor[k] = v[i]->destructor;
3508 symbol_type_tag[k] = v[i]->tag;
3515 symbol_pname = TMALLOC(char *, nsyms);
3516 NO_SPACE(symbol_pname);
3518 for (i = 0; i < nsyms; ++i)
3519 protect_string(symbol_name[i], &(symbol_pname[i]));
3533 ritem = TMALLOC(Value_t, nitems);
3536 rlhs = TMALLOC(Value_t, nrules);
3539 rrhs = TMALLOC(Value_t, nrules + 1);
3542 rprec = TREALLOC(Value_t, rprec, nrules);
3545 rassoc = TREALLOC(Assoc_t, rassoc, nrules);
3549 ritem[1] = goal->index;
3554 rlhs[2] = start_symbol;
3560 for (i = 3; i < nrules; ++i)
3562 #if defined(YYBTYACC)
3563 if (plhs[i]->args > 0)
3565 if (plhs[i]->argnames)
3567 FREE(plhs[i]->argnames);
3568 plhs[i]->argnames = NULL;
3570 if (plhs[i]->argtags)
3572 FREE(plhs[i]->argtags);
3573 plhs[i]->argtags = NULL;
3576 #endif /* defined(YYBTYACC) */
3577 rlhs[i] = plhs[i]->index;
3583 ritem[j] = pitem[j]->index;
3584 if (pitem[j]->class == TERM)
3586 prec2 = pitem[j]->prec;
3587 assoc = pitem[j]->assoc;
3591 ritem[j] = (Value_t)-i;
3593 if (rprec[i] == UNDEFINED)
3603 #if defined(YYBTYACC)
3612 size_t j, spacing = 0;
3613 FILE *f = verbose_file;
3619 for (i = 2; i < nrules; ++i)
3621 if (rlhs[i] != rlhs[i - 1])
3625 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
3626 spacing = strlen(symbol_name[rlhs[i]]) + 1;
3630 fprintf(f, "%4d ", i - 2);
3637 while (ritem[k] >= 0)
3639 fprintf(f, " %s", symbol_name[ritem[k]]);
3647 #if defined(YYBTYACC)
3649 finalize_destructors(void)
3655 for (i = 2; i < nsyms; ++i)
3657 tag = symbol_type_tag[i];
3658 if (symbol_destructor[i] == NULL)
3661 { /* use <> destructor, if there is one */
3662 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3664 symbol_destructor[i] = TMALLOC(char,
3665 strlen(bp->destructor) + 1);
3666 NO_SPACE(symbol_destructor[i]);
3667 strcpy(symbol_destructor[i], bp->destructor);
3671 { /* use type destructor for this tag, if there is one */
3672 bp = lookup_type_destructor(tag);
3673 if (bp->destructor != NULL)
3675 symbol_destructor[i] = TMALLOC(char,
3676 strlen(bp->destructor) + 1);
3677 NO_SPACE(symbol_destructor[i]);
3678 strcpy(symbol_destructor[i], bp->destructor);
3681 { /* use <*> destructor, if there is one */
3682 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3683 /* replace "$$" with "(*val).tag" in destructor code */
3684 symbol_destructor[i]
3685 = process_destructor_XX(bp->destructor, tag);
3690 { /* replace "$$" with "(*val)[.tag]" in destructor code */
3691 symbol_destructor[i]
3692 = process_destructor_XX(symbol_destructor[i], tag);
3695 /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */
3696 DO_FREE(symbol_type_tag); /* no longer needed */
3697 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3700 /* 'bp->tag' is a static value, don't free */
3701 FREE(bp->destructor);
3704 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3707 /* 'bp->tag' is a static value, don't free */
3708 FREE(bp->destructor);
3711 if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL)
3718 /* 'bp->tag' freed by 'free_tags()' */
3719 FREE(bp->destructor);
3724 #endif /* defined(YYBTYACC) */
3729 write_section(code_file, banner);
3730 create_symbol_table();
3731 read_declarations();
3733 free_symbol_table();
3740 #if defined(YYBTYACC)
3742 finalize_destructors();
3749 free_declarations(param *list)
3753 param *next = list->next;
3766 lex_param = free_declarations(lex_param);
3767 parse_param = free_declarations(parse_param);
3777 DO_FREE(symbol_name);
3778 DO_FREE(symbol_prec);
3779 DO_FREE(symbol_assoc);
3780 DO_FREE(symbol_value);
3781 #if defined(YYBTYACC)
3782 DO_FREE(symbol_pval);
3783 DO_FREE(symbol_destructor);
3784 DO_FREE(symbol_type_tag);