1 /* $Id: reader.c,v 1.73 2017/07/09 19:15:35 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]);
147 if (isspace(UCH(ch)))
156 if (isspace(UCH(ch)))
162 UNLESS(strncmp(line + n, "line", 4));
170 UNLESS(!isspace(UCH(line[n])));
174 if (isspace(UCH(ch)))
179 UNLESS(!isdigit(UCH(ch)));
184 if (isdigit(UCH(ch)))
189 UNLESS(!isspace(UCH(ch)));
193 if (isspace(UCH(ch)))
199 UNLESS(line[n + 1] == '"');
219 size_t need = (size_t) (name_end - name_1st);
220 if ((long)need > (long)input_file_name_len)
222 input_file_name_len = ((need + 1) * 3) / 2;
223 input_file_name = TREALLOC(char, input_file_name, input_file_name_len);
224 NO_SPACE(input_file_name);
228 memcpy(input_file_name, line + name_1st + 1, need - 1);
229 input_file_name[need - 1] = '\0';
233 input_file_name[0] = '\0';
237 if (ld >= ldNUM && ld < ldERR)
241 lineno = (int)strtol(line + line_1st, NULL, 10) - 1;
256 FILE *f = input_file;
262 if (saw_eof || (c = getc(f)) == EOF)
274 if (line == NULL || linesize != (LINESIZE + 1))
278 linesize = LINESIZE + 1;
279 line = TMALLOC(char, linesize);
290 if ((i + 3) >= linesize)
292 linesize += LINESIZE;
293 line = TREALLOC(char, line, linesize);
306 while (line_directive());
321 p = TMALLOC(char, s - line + 1);
326 while ((*t++ = *s++) != '\n')
337 a.a_line = dup_line();
338 a.a_cptr = a.a_line + (cptr - line);
343 if (*s == '*' && s[1] == '/')
353 unterminated_comment(&a);
386 else if (s[1] == '/')
411 switch (ch = next_inline())
438 static struct keyword
444 { "binary", NONASSOC },
445 { "debug", XXXDEBUG },
446 #if defined(YYBTYACC)
447 { "destructor", DESTRUCTOR },
449 { "error-verbose",ERROR_VERBOSE },
450 { "expect", EXPECT },
451 { "expect-rr", EXPECT_RR },
453 #if defined(YYBTYACC)
454 { "initial-action", INITIAL_ACTION },
457 { "lex-param", LEX_PARAM },
458 #if defined(YYBTYACC)
459 { "locations", LOCATIONS },
461 { "nonassoc", NONASSOC },
462 { "parse-param", PARSE_PARAM },
463 { "pure-parser", PURE_PARSER },
468 { "token-table", TOKEN_TABLE },
471 { "yacc", POSIX_YACC },
476 compare_keys(const void *a, const void *b)
478 const struct keyword *p = (const struct keyword *)a;
479 const struct keyword *q = (const struct keyword *)b;
480 return strcmp(p->name, q->name);
502 else if (isdigit(UCH(c))
511 /* treat keywords spelled with '_' as if it were '-' */
522 if ((key = bsearch(cache, keywords,
523 sizeof(keywords) / sizeof(*key),
524 sizeof(*key), compare_keys)))
532 if (c == '%' || c == '\\')
543 syntax_error(lineno, line, t_cptr);
551 FILE *f = output_file;
557 syntax_error(lineno, line, cptr);
559 fprintf(f, "#ident \"");
579 copy_string(int quote)
581 struct mstring *temp = msnew();
585 a.a_line = dup_line();
586 a.a_cptr = a.a_line + (cptr - line - 1);
598 unterminated_string(&a);
607 unterminated_string(&a);
616 struct mstring *temp = msnew();
623 while ((c = *++cptr) != '\n')
626 if (c == '*' && cptr[1] == '/')
636 a.a_line = dup_line();
637 a.a_cptr = a.a_line + (cptr - line - 1);
645 if (c == '*' && *cptr == '/')
656 unterminated_comment(&a);
668 int need_newline = 0;
671 a.a_line = dup_line();
672 a.a_cptr = a.a_line + (cptr - line - 2);
678 unterminated_text(&a);
681 fprintf(f, line_format, lineno, input_file_name);
693 unterminated_text(&a);
699 char *s = copy_string(c);
709 char *s = copy_comment();
736 puts_both(const char *s)
740 fputs(s, union_file);
758 a.a_line = dup_line();
759 a.a_cptr = a.a_line + (cptr - line - 6);
762 over_unionized(cptr - 6);
765 puts_both("#ifdef YYSTYPE\n");
766 puts_both("#undef YYSTYPE_IS_DECLARED\n");
767 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
768 puts_both("#endif\n");
769 puts_both("#ifndef YYSTYPE_IS_DECLARED\n");
770 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
773 fprintf(text_file, line_format, lineno, input_file_name);
774 puts_both("typedef union");
785 unterminated_union(&a);
795 puts_both(" YYSTYPE;\n");
796 puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n");
805 char *s = copy_string(c);
813 char *s = copy_comment();
825 after_blanks(char *s)
827 while (*s != '\0' && isspace(UCH(*s)))
833 * Trim leading/trailing blanks, and collapse multiple embedded blanks to a
834 * single space. Return index to last character in the buffer.
837 trim_blanks(char *buffer)
842 char *s = after_blanks(d);
844 while ((*d++ = *s++) != '\0')
850 while ((--d != buffer) && isspace(UCH(*d)))
853 for (s = d = buffer; (*d++ = *s++) != '\0';)
855 if (isspace(UCH(*s)))
858 while (isspace(UCH(*s)))
867 return (int)strlen(buffer) - 1;
871 * Scan forward in the current line-buffer looking for a right-curly bracket.
873 * Parameters begin with a left-curly bracket, and continue until there are no
874 * more interesting characters after the last right-curly bracket on the
875 * current line. Bison documents parameters as separated like this:
876 * {type param1} {type2 param2}
877 * but also accepts commas (although some versions of bison mishandle this)
878 * {type param1, type2 param2}
888 switch (next_inline())
907 save_param(int k, char *buffer, int name, int type2)
911 p = TMALLOC(param, 1);
914 p->type2 = strdup(buffer + type2);
916 buffer[type2] = '\0';
917 (void)trim_blanks(p->type2);
919 p->name = strdup(buffer + name);
922 (void)trim_blanks(p->name);
924 p->type = strdup(buffer);
926 (void)trim_blanks(p->type);
950 * Keep a linked list of parameters. This may be multi-line, if the trailing
951 * right-curly bracket is absent.
962 int st_lineno = lineno;
996 if ((curly == 1) && (cptr == line))
1006 if (curly == 0 && !isspace(UCH(c)))
1014 buf_size = (size_t) linesize;
1015 buf = TMALLOC(char, buf_size);
1023 buf_size += (size_t) linesize;
1024 buf = TREALLOC(char, buf, buf_size);
1029 if ((state == 2) && (c == L_CURL))
1033 else if ((state == 2) && isspace(UCH(c)))
1037 else if ((c != L_CURL) && (c != R_CURL))
1044 while (curly < 2 || more_curly());
1057 (void)trim_blanks(buf);
1062 char *parms = (comma + 1);
1063 comma = strchr(parms, ',');
1067 (void)trim_blanks(parms);
1068 i = (int)strlen(parms) - 1;
1074 if (parms[i] == ']')
1077 while (i >= 0 && level > 0 && parms[i] != '[')
1079 if (parms[i] == ']')
1081 else if (parms[i] == '[')
1094 while (i > 0 && (isalnum(UCH(parms[i])) || UCH(parms[i]) == '_'))
1097 if (!isspace(UCH(parms[i])) && parms[i] != '*')
1102 save_param(k, parms, name, type2);
1110 syntax_error(lineno, line, cptr);
1116 if (c >= '0' && c <= '9')
1118 if (c >= 'A' && c <= 'F')
1119 return (c - 'A' + 10);
1120 if (c >= 'a' && c <= 'f')
1121 return (c - 'a' + 10);
1134 a.a_lineno = lineno;
1135 a.a_line = dup_line();
1136 a.a_cptr = a.a_line + (cptr - line);
1146 unterminated_string(&a);
1149 char *c_cptr = cptr - 1;
1157 unterminated_string(&a);
1172 n = (n << 3) + (c - '0');
1176 n = (n << 3) + (c - '0');
1181 illegal_character(c_cptr);
1188 if (n < 0 || n >= 16)
1189 illegal_character(c_cptr);
1194 if (i < 0 || i >= 16)
1199 illegal_character(c_cptr);
1232 s = TMALLOC(char, n);
1235 for (i = 0; i < n; ++i)
1244 for (i = 0; i < n; ++i)
1247 if (c == '\\' || c == cache[0])
1252 else if (isprint(UCH(c)))
1281 cachec(((c >> 6) & 7) + '0');
1282 cachec(((c >> 3) & 7) + '0');
1283 cachec((c & 7) + '0');
1297 if (n == 1 && bp->value == UNDEFINED)
1298 bp->value = UCH(*s);
1305 is_reserved(char *name)
1309 if (strcmp(name, ".") == 0 ||
1310 strcmp(name, "$accept") == 0 ||
1311 strcmp(name, "$end") == 0)
1314 if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2])))
1317 while (isdigit(UCH(*s)))
1332 for (c = *cptr; IS_IDENT(c); c = *++cptr)
1336 if (is_reserved(cache))
1337 used_reserved(cache);
1339 return (lookup(cache));
1350 for (c = *cptr; isdigit(UCH(c)); c = *++cptr)
1352 n = (10 * n + (c - '0'));
1355 syntax_error(lineno, line, base);
1361 return (Value_t)(n);
1365 cache_tag(char *tag, size_t len)
1370 for (i = 0; i < ntags; ++i)
1372 if (strncmp(tag, tag_table[i], len) == 0 &&
1373 tag_table[i][len] == NUL)
1374 return (tag_table[i]);
1377 if (ntags >= tagmax)
1382 ? TREALLOC(char *, tag_table, tagmax)
1383 : TMALLOC(char *, tagmax));
1384 NO_SPACE(tag_table);
1387 s = TMALLOC(char, len + 1);
1390 strncpy(s, tag, len);
1392 tag_table[ntags++] = s;
1400 int t_lineno = lineno;
1401 char *t_line = dup_line();
1402 char *t_cptr = t_line + (cptr - line);
1409 illegal_tag(t_lineno, t_line, t_cptr);
1417 while (IS_IDENT(c));
1424 illegal_tag(t_lineno, t_line, t_cptr);
1429 return cache_tag(cache, (size_t) cinc);
1432 #if defined(YYBTYACC)
1438 while (IS_NAME2(UCH(*cptr)))
1440 return cache_tag(b, (size_t) (cptr - b));
1445 declare_tokens(int assoc)
1468 if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
1470 else if (c == '\'' || c == '"')
1476 tokenized_start(bp->name);
1481 if (bp->tag && tag != bp->tag)
1482 retyped_warning(bp->name);
1488 if (bp->prec && prec != bp->prec)
1489 reprec_warning(bp->name);
1490 bp->assoc = (Assoc_t)assoc;
1498 if (isdigit(UCH(c)))
1500 value = get_number();
1501 if (bp->value != UNDEFINED && value != bp->value)
1502 revalued_warning(bp->name);
1512 * %expect requires special handling
1513 * as it really isn't part of the yacc
1514 * grammar only a flag for yacc proper.
1517 declare_expect(int assoc)
1521 if (assoc != EXPECT && assoc != EXPECT_RR)
1525 * Stay away from nextc - doesn't
1526 * detect EOL and will read to EOF.
1534 if (isdigit(UCH(c)))
1536 if (assoc == EXPECT)
1537 SRexpect = get_number();
1539 RRexpect = get_number();
1543 * Looking for number before EOL.
1544 * Spaces, tabs, and numbers are ok,
1545 * words, punc., etc. are syntax errors.
1547 else if (c == '\n' || isalpha(UCH(c)) || !isspace(UCH(c)))
1549 syntax_error(lineno, line, cptr);
1560 #if defined(YYBTYACC)
1562 declare_argtypes(bucket *bp)
1564 char *tags[MAXARGS];
1568 retyped_warning(bp->name);
1569 cptr++; /* skip open paren */
1576 syntax_error(lineno, line, cptr);
1577 tags[args++] = get_tag();
1584 cptr++; /* skip close paren */
1586 bp->argnames = TMALLOC(char *, args);
1587 NO_SPACE(bp->argnames);
1588 bp->argtags = CALLOC(sizeof(char *), args + 1);
1589 NO_SPACE(bp->argtags);
1592 bp->argtags[args] = tags[args];
1593 bp->argnames[args] = NULL;
1616 if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
1619 #if defined(YYBTYACC)
1620 if (nextc() == L_PAREN)
1621 declare_argtypes(bp);
1626 else if (c == '\'' || c == '"')
1629 #if defined(YYBTYACC)
1638 if (bp->tag && tag != bp->tag)
1639 retyped_warning(bp->name);
1654 if (!isalpha(UCH(c)) && c != '_' && c != '.' && c != '$')
1655 syntax_error(lineno, line, cptr);
1657 if (bp->class == TERM)
1658 terminal_start(bp->name);
1659 if (goal && goal != bp)
1660 restarted_warning();
1665 read_declarations(void)
1669 cache_size = CACHE_SIZE;
1670 cache = TMALLOC(char, cache_size);
1679 syntax_error(lineno, line, cptr);
1680 switch (k = keyword())
1734 #if defined(YYBTYACC)
1743 case INITIAL_ACTION:
1744 copy_initial_action();
1753 /* noop for bison compatibility. byacc is already designed to be posix
1754 * yacc compatible. */
1761 initialize_grammar(void)
1766 pitem = TMALLOC(bucket *, maxitems);
1777 plhs = TMALLOC(bucket *, maxrules);
1784 rprec = TMALLOC(Value_t, maxrules);
1791 rassoc = TMALLOC(Assoc_t, maxrules);
1803 pitem = TREALLOC(bucket *, pitem, maxitems);
1812 plhs = TREALLOC(bucket *, plhs, maxrules);
1815 rprec = TREALLOC(Value_t, rprec, maxrules);
1818 rassoc = TREALLOC(Assoc_t, rassoc, maxrules);
1822 /* set immediately prior to where copy_args() could be called, and incremented by
1823 the various routines that will rescan the argument list as appropriate */
1824 static int rescan_lineno;
1825 #if defined(YYBTYACC)
1828 copy_args(int *alen)
1830 struct mstring *s = msnew();
1831 int depth = 0, len = 1;
1835 a.a_lineno = lineno;
1836 a.a_line = dup_line();
1837 a.a_cptr = a.a_line + (cptr - line - 1);
1839 while ((c = *cptr++) != R_PAREN || depth || quote)
1841 if (c == ',' && !quote && !depth)
1854 unterminated_string(&a);
1856 unterminated_arglist(&a);
1873 else if (c == R_PAREN)
1875 else if (c == '\"' || c == '\'')
1886 parse_id(char *p, char **save)
1890 while (isspace(UCH(*p)))
1893 if (!isalpha(UCH(*p)) && *p != '_')
1896 while (IS_NAME2(UCH(*p)))
1900 *save = cache_tag(b, (size_t) (p - b));
1906 parse_int(char *p, int *save)
1908 int neg = 0, val = 0;
1910 while (isspace(UCH(*p)))
1918 if (!isdigit(UCH(*p)))
1920 while (isdigit(UCH(*p)))
1921 val = val * 10 + *p++ - '0';
1930 parse_arginfo(bucket *a, char *args, int argslen)
1932 char *p = args, *tmp;
1937 if (a->args != argslen)
1938 arg_number_disagree_warning(rescan_lineno, a->name);
1943 if ((a->args = argslen) == 0)
1945 a->argnames = TMALLOC(char *, argslen);
1946 NO_SPACE(a->argnames);
1947 a->argtags = TMALLOC(char *, argslen);
1948 NO_SPACE(a->argtags);
1952 for (i = 0; i < argslen; i++)
1954 while (isspace(UCH(*p)))
1959 while (isspace(UCH(*p)))
1965 if (!(p = parse_id(p + 1, &tmp)))
1967 while (isspace(UCH(*p)))
1974 if (a->argtags[i] != tmp)
1975 arg_type_disagree_warning(rescan_lineno, i + 1, a->name);
1978 a->argtags[i] = tmp;
1981 a->argtags[i] = NULL;
1982 if (!(p = parse_id(p, &a->argnames[i])))
1984 while (isspace(UCH(*p)))
1994 compile_arg(char **theptr, char *yyvaltag)
1997 struct mstring *c = msnew();
1999 Value_t *offsets = NULL, maxoffset;
2004 for (i = nitems - 1; pitem[i]; --i)
2007 if (pitem[i]->class != ARGUMENT)
2012 offsets = TMALLOC(Value_t, maxoffset + 1);
2015 for (j = 0, i++; i < nitems; i++)
2016 if (pitem[i]->class != ARGUMENT)
2017 offsets[++j] = (Value_t)(i - nitems + 1);
2019 rhs = pitem + nitems - 1;
2022 msprintf(c, "yyval.%s = ", yyvaltag);
2024 msprintf(c, "yyval = ");
2031 if (!(p = parse_id(++p, &tag)) || *p++ != '>')
2032 illegal_tag(rescan_lineno, NULL, NULL);
2033 if (isdigit(UCH(*p)) || *p == '-')
2036 if (!(p = parse_int(p, &val)))
2037 dollar_error(rescan_lineno, NULL, NULL);
2040 else if (val > maxoffset)
2042 dollar_warning(rescan_lineno, val);
2043 i = val - maxoffset;
2045 else if (maxoffset > 0)
2048 if (!tag && !(tag = rhs[i]->tag) && havetags)
2049 untyped_rhs(val, rhs[i]->name);
2051 msprintf(c, "yystack.l_mark[%d]", i);
2053 msprintf(c, ".%s", tag);
2057 else if (isalpha(UCH(*p)) || *p == '_')
2060 if (!(p = parse_id(p, &arg)))
2061 dollar_error(rescan_lineno, NULL, NULL);
2062 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2063 if (arg == plhs[nrules]->argnames[i])
2066 unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL);
2068 tag = plhs[nrules]->argtags[i];
2069 msprintf(c, "yystack.l_mark[%d]",
2070 i - plhs[nrules]->args + 1 - n);
2072 msprintf(c, ".%s", tag);
2074 untyped_arg_warning(rescan_lineno, "$", arg);
2077 dollar_error(rescan_lineno, NULL, NULL);
2081 at_error(rescan_lineno, NULL, NULL);
2097 can_elide_arg(char **theptr, char *yyvaltag)
2102 Value_t *offsets = NULL, maxoffset = 0;
2110 if (!(p = parse_id(++p, &tag)) || *p++ != '>')
2113 for (i = nitems - 1; pitem[i]; --i)
2116 if (pitem[i]->class != ARGUMENT)
2121 offsets = TMALLOC(Value_t, maxoffset + 1);
2124 for (j = 0, i++; i < nitems; i++)
2125 if (pitem[i]->class != ARGUMENT)
2126 offsets[++j] = (Value_t)(i - nitems + 1);
2128 rhs = pitem + nitems - 1;
2130 if (isdigit(UCH(*p)) || *p == '-')
2133 if (!(p = parse_int(p, &val)))
2139 else if (val > maxoffset)
2150 else if (isalpha(UCH(*p)) || *p == '_')
2153 if (!(p = parse_id(p, &arg)))
2155 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2156 if (arg == plhs[nrules]->argnames[i])
2161 tag = plhs[nrules]->argtags[i];
2162 rv = plhs[nrules]->args + n - i;
2165 if (tag && yyvaltag)
2167 if (strcmp(tag, yyvaltag))
2170 else if (tag || yyvaltag)
2180 #define ARG_CACHE_SIZE 1024
2181 static struct arg_cache
2183 struct arg_cache *next;
2187 *arg_cache[ARG_CACHE_SIZE];
2190 lookup_arg_cache(char *code)
2192 struct arg_cache *entry;
2194 entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE];
2197 if (!strnscmp(entry->code, code))
2199 entry = entry->next;
2205 insert_arg_cache(char *code, int rule)
2207 struct arg_cache *entry = NEW(struct arg_cache);
2211 i = strnshash(code) % ARG_CACHE_SIZE;
2214 entry->next = arg_cache[i];
2215 arg_cache[i] = entry;
2219 clean_arg_cache(void)
2221 struct arg_cache *e, *t;
2224 for (i = 0; i < ARG_CACHE_SIZE; i++)
2226 for (e = arg_cache[i]; (t = e); e = e->next, FREE(t))
2228 arg_cache[i] = NULL;
2231 #endif /* defined(YYBTYACC) */
2234 advance_to_start(void)
2240 #if defined(YYBTYACC)
2265 syntax_error(lineno, line, s_cptr);
2270 if (!isalpha(UCH(c)) && c != '_' && c != '.' && c != '_')
2271 syntax_error(lineno, line, cptr);
2275 if (bp->class == TERM)
2276 terminal_start(bp->name);
2284 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2285 #if defined(YYBTYACC)
2289 args = copy_args(&argslen);
2295 syntax_error(lineno, line, cptr);
2296 start_rule(bp, s_lineno);
2297 #if defined(YYBTYACC)
2298 parse_arginfo(bp, args, argslen);
2304 start_rule(bucket *bp, int s_lineno)
2306 if (bp->class == TERM)
2307 terminal_lhs(s_lineno);
2308 bp->class = NONTERM;
2311 if (nrules >= maxrules)
2314 rprec[nrules] = UNDEFINED;
2315 rassoc[nrules] = TOKEN;
2323 if (!last_was_action && plhs[nrules]->tag)
2325 if (pitem[nitems - 1])
2327 for (i = nitems - 1; (i > 0) && pitem[i]; --i)
2329 if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag)
2330 default_action_warning(plhs[nrules]->name);
2333 default_action_warning(plhs[nrules]->name);
2336 last_was_action = 0;
2337 if (nitems >= maxitems)
2345 insert_empty_rule(void)
2350 assert(cache_size >= CACHE_SIZE);
2351 sprintf(cache, "$$%d", ++gensym);
2352 bp = make_bucket(cache);
2353 last_symbol->next = bp;
2355 bp->tag = plhs[nrules]->tag;
2357 #if defined(YYBTYACC)
2361 nitems = (Value_t)(nitems + 2);
2362 if (nitems > maxitems)
2364 bpp = pitem + nitems - 1;
2366 while ((bpp[0] = bpp[-1]) != 0)
2369 if (++nrules >= maxrules)
2371 plhs[nrules] = plhs[nrules - 1];
2372 plhs[nrules - 1] = bp;
2373 rprec[nrules] = rprec[nrules - 1];
2374 rprec[nrules - 1] = 0;
2375 rassoc[nrules] = rassoc[nrules - 1];
2376 rassoc[nrules - 1] = TOKEN;
2379 #if defined(YYBTYACC)
2381 insert_arg_rule(char *arg, char *tag)
2383 int line_number = rescan_lineno;
2384 char *code = compile_arg(&arg, tag);
2385 int rule = lookup_arg_cache(code);
2386 FILE *f = action_file;
2391 insert_arg_cache(code, rule);
2392 trialaction = 1; /* arg rules always run in trial mode */
2393 fprintf(f, "case %d:\n", rule - 2);
2395 fprintf(f, line_format, line_number, input_file_name);
2396 fprintf(f, "%s;\n", code);
2397 fprintf(f, "break;\n");
2398 insert_empty_rule();
2399 plhs[rule]->tag = cache_tag(tag, strlen(tag));
2400 plhs[rule]->class = ARGUMENT;
2404 if (++nitems > maxitems)
2406 pitem[nitems - 1] = plhs[rule];
2418 int s_lineno = lineno;
2419 #if defined(YYBTYACC)
2425 if (c == '\'' || c == '"')
2431 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2432 #if defined(YYBTYACC)
2436 args = copy_args(&argslen);
2444 start_rule(bp, s_lineno);
2445 #if defined(YYBTYACC)
2446 parse_arginfo(bp, args, argslen);
2452 if (last_was_action)
2453 insert_empty_rule();
2454 last_was_action = 0;
2456 #if defined(YYBTYACC)
2459 if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL)
2462 if (plhs[nrules]->args != bp->args)
2463 wrong_number_args_warning("default ", bp->name);
2464 for (i = bp->args - 1; i >= 0; i--)
2465 if (plhs[nrules]->argtags[i] != bp->argtags[i])
2466 wrong_type_for_arg_warning(i + 1, bp->name);
2468 else if (bp->args != argslen)
2469 wrong_number_args_warning("", bp->name);
2474 int elide_cnt = can_elide_arg(&ap, bp->argtags[0]);
2476 if (elide_cnt > argslen)
2480 for (i = 1; i < elide_cnt; i++)
2481 if (can_elide_arg(&ap, bp->argtags[i]) != elide_cnt - i)
2489 assert(i == elide_cnt);
2496 for (; i < argslen; i++)
2497 ap = insert_arg_rule(ap, bp->argtags[i]);
2500 #endif /* defined(YYBTYACC) */
2502 if (++nitems > maxitems)
2504 pitem[nitems - 1] = bp;
2513 #if defined(YYBTYACC)
2517 FILE *f = action_file;
2519 Value_t *offsets = NULL, maxoffset;
2522 a.a_lineno = lineno;
2523 a.a_line = dup_line();
2524 a.a_cptr = a.a_line + (cptr - line);
2526 if (last_was_action)
2527 insert_empty_rule();
2528 last_was_action = 1;
2529 #if defined(YYBTYACC)
2530 trialaction = (*cptr == L_BRAC);
2533 fprintf(f, "case %d:\n", nrules - 2);
2534 #if defined(YYBTYACC)
2538 fprintf(f, " if (!yytrial)\n");
2542 fprintf(f, line_format, lineno, input_file_name);
2546 /* avoid putting curly-braces in first column, to ease editing */
2547 if (*after_blanks(cptr) == L_CURL)
2550 cptr = after_blanks(cptr);
2555 for (i = nitems - 1; pitem[i]; --i)
2558 if (pitem[i]->class != ARGUMENT)
2563 offsets = TMALLOC(Value_t, maxoffset + 1);
2566 for (j = 0, i++; i < nitems; i++)
2568 if (pitem[i]->class != ARGUMENT)
2570 offsets[++j] = (Value_t)(i - nitems + 1);
2574 rhs = pitem + nitems - 1;
2583 int d_lineno = lineno;
2584 char *d_line = dup_line();
2585 char *d_cptr = d_line + (cptr - line);
2592 fprintf(f, "yyval.%s", tag);
2597 else if (isdigit(UCH(c)))
2601 fprintf(f, "yystack.l_mark[%d].%s", -n, tag);
2602 else if (i > maxoffset)
2604 dollar_warning(d_lineno, i);
2605 fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag);
2608 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2612 else if (c == '-' && isdigit(UCH(cptr[1])))
2615 i = -get_number() - n;
2616 fprintf(f, "yystack.l_mark[%d].%s", i, tag);
2620 #if defined(YYBTYACC)
2621 else if (isalpha(UCH(c)) || c == '_')
2623 char *arg = scan_id();
2624 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2625 if (arg == plhs[nrules]->argnames[i])
2628 unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr);
2629 fprintf(f, "yystack.l_mark[%d].%s",
2630 i - plhs[nrules]->args + 1 - n, tag);
2636 dollar_error(d_lineno, d_line, d_cptr);
2638 else if (cptr[1] == '$')
2642 tag = plhs[nrules]->tag;
2645 fprintf(f, "yyval.%s", tag);
2648 fprintf(f, "yyval");
2650 #if defined(YYBTYACC)
2655 else if (isdigit(UCH(cptr[1])))
2659 if (havetags && offsets)
2661 if (i <= 0 || i > maxoffset)
2663 tag = rhs[offsets[i]]->tag;
2665 untyped_rhs(i, rhs[offsets[i]]->name);
2666 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2671 fprintf(f, "yystack.l_mark[%d]", -n);
2672 else if (i > maxoffset)
2674 dollar_warning(lineno, i);
2675 fprintf(f, "yystack.l_mark[%d]", i - maxoffset);
2678 fprintf(f, "yystack.l_mark[%d]", offsets[i]);
2682 else if (cptr[1] == '-')
2688 fprintf(f, "yystack.l_mark[%d]", -i - n);
2691 #if defined(YYBTYACC)
2692 else if (isalpha(UCH(cptr[1])) || cptr[1] == '_')
2697 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2698 if (arg == plhs[nrules]->argnames[i])
2701 unknown_arg_warning(lineno, "$", arg, line, cptr);
2702 tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]);
2703 fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n);
2705 fprintf(f, ".%s", tag);
2707 untyped_arg_warning(lineno, "$", arg);
2712 #if defined(YYBTYACC)
2717 int l_lineno = lineno;
2718 char *l_line = dup_line();
2719 char *l_cptr = l_line + (cptr - line);
2720 syntax_error(l_lineno, l_line, l_cptr);
2724 fprintf(f, "yyloc");
2728 else if (isdigit(UCH(cptr[1])))
2733 fprintf(f, "yystack.p_mark[%d]", -n);
2734 else if (i > maxoffset)
2736 at_warning(lineno, i);
2737 fprintf(f, "yystack.p_mark[%d]", i - maxoffset);
2740 fprintf(f, "yystack.p_mark[%d]", offsets[i]);
2743 else if (cptr[1] == '-')
2747 fprintf(f, "yystack.p_mark[%d]", -i - n);
2759 while (IS_NAME2(c));
2763 #if defined(YYBTYACC)
2766 if (trialaction && c == L_BRAC && depth == 0)
2772 if (trialaction && c == R_BRAC && depth == 1)
2777 if (c == L_BRAC && !haveyyval)
2781 if (c == L_CURL && !haveyyval)
2783 fprintf(f, " if (!yytrial)\n");
2785 fprintf(f, line_format, lineno, input_file_name);
2789 fprintf(f, "\nbreak;\n");
2804 unterminated_action(&a);
2809 fprintf(f, "\nbreak;\n");
2815 #if defined(YYBTYACC)
2834 #if defined(YYBTYACC)
2838 if (c == L_BRAC && !haveyyval)
2843 if (c == L_CURL && !haveyyval)
2845 fprintf(f, " if (!yytrial)\n");
2847 fprintf(f, line_format, lineno, input_file_name);
2852 fprintf(f, "\nbreak;\n");
2861 char *s = copy_string(c);
2869 char *s = copy_comment();
2880 #if defined(YYBTYACC)
2882 get_code(struct ainfo *a, const char *loc)
2887 struct mstring *code_mstr = msnew();
2890 msprintf(code_mstr, line_format, lineno, input_file_name);
2892 cptr = after_blanks(cptr);
2893 if (*cptr == L_CURL)
2894 /* avoid putting curly-braces in first column, to ease editing */
2895 mputc(code_mstr, '\t');
2897 syntax_error(lineno, line, cptr);
2899 a->a_lineno = lineno;
2900 a->a_line = dup_line();
2901 a->a_cptr = a->a_line + (cptr - line);
2910 int d_lineno = lineno;
2911 char *d_line = dup_line();
2912 char *d_cptr = d_line + (cptr - line);
2919 msprintf(code_mstr, "(*val).%s", tag);
2925 dollar_error(d_lineno, d_line, d_cptr);
2927 else if (cptr[1] == '$')
2929 /* process '$$' later; replacement is context dependent */
2930 msprintf(code_mstr, "$$");
2935 if (c == '@' && cptr[1] == '$')
2939 int l_lineno = lineno;
2940 char *l_line = dup_line();
2941 char *l_cptr = l_line + (cptr - line);
2942 syntax_error(l_lineno, l_line, l_cptr);
2944 msprintf(code_mstr, "%s", loc);
2952 mputc(code_mstr, c);
2955 while (IS_NAME2(c));
2959 mputc(code_mstr, c);
2966 unterminated_action(a);
2980 char *s = copy_string(c);
2981 msprintf(code_mstr, "%s", s);
2988 char *s = copy_comment();
2989 msprintf(code_mstr, "%s", s);
2998 return msdone(code_mstr);
3002 copy_initial_action(void)
3006 initial_action = get_code(&a, "yyloc");
3011 copy_destructor(void)
3018 code_text = get_code(&a, "(*loc)");
3028 { /* "no semantic type" default destructor */
3030 if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL)
3032 static char untyped_default[] = "<>";
3033 bp = make_bucket("untyped default");
3034 bp->tag = untyped_default;
3035 default_destructor[UNTYPED_DEFAULT] = bp;
3037 if (bp->destructor != NULL)
3038 destructor_redeclared_warning(&a);
3040 /* replace "$$" with "(*val)" in destructor code */
3041 bp->destructor = process_destructor_XX(code_text, NULL);
3043 else if (cptr[1] == '*' && cptr[2] == '>')
3044 { /* "no per-symbol or per-type" default destructor */
3046 if ((bp = default_destructor[TYPED_DEFAULT]) == NULL)
3048 static char typed_default[] = "<*>";
3049 bp = make_bucket("typed default");
3050 bp->tag = typed_default;
3051 default_destructor[TYPED_DEFAULT] = bp;
3053 if (bp->destructor != NULL)
3054 destructor_redeclared_warning(&a);
3057 /* postpone re-processing destructor $$s until end of grammar spec */
3058 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
3059 NO_SPACE(bp->destructor);
3060 strcpy(bp->destructor, code_text);
3064 { /* "semantic type" default destructor */
3065 char *tag = get_tag();
3066 bp = lookup_type_destructor(tag);
3067 if (bp->destructor != NULL)
3068 destructor_redeclared_warning(&a);
3070 /* replace "$$" with "(*val).tag" in destructor code */
3071 bp->destructor = process_destructor_XX(code_text, tag);
3074 else if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
3075 { /* "symbol" destructor */
3077 if (bp->destructor != NULL)
3078 destructor_redeclared_warning(&a);
3081 /* postpone re-processing destructor $$s until end of grammar spec */
3082 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
3083 NO_SPACE(bp->destructor);
3084 strcpy(bp->destructor, code_text);
3095 process_destructor_XX(char *code, char *tag)
3100 struct mstring *new_code = msnew();
3101 char *codeptr = code;
3104 loop: /* step thru code */
3106 if (c == '$' && codeptr[1] == '$')
3110 msprintf(new_code, "(*val)");
3112 msprintf(new_code, "(*val).%s", tag);
3122 while (IS_NAME2(c));
3136 return msdone(new_code);
3164 if (c == '*' && *codeptr == '/')
3166 mputc(new_code, '/');
3178 #endif /* defined(YYBTYACC) */
3187 if (c == '%' || c == '\\')
3195 else if ((c == 'p' || c == 'P') &&
3196 ((c = cptr[2]) == 'r' || c == 'R') &&
3197 ((c = cptr[3]) == 'e' || c == 'E') &&
3198 ((c = cptr[4]) == 'c' || c == 'C') &&
3199 ((c = cptr[5], !IS_IDENT(c))))
3202 syntax_error(lineno, line, cptr);
3205 if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
3207 else if (c == '\'' || c == '"')
3211 syntax_error(lineno, line, cptr);
3215 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
3218 rprec[nrules] = bp->prec;
3219 rassoc[nrules] = bp->assoc;
3228 initialize_grammar();
3243 #if defined(YYBTYACC)
3244 else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC))
3246 else if (c == L_CURL || c == '=')
3252 start_rule(plhs[nrules - 1], 0);
3261 syntax_error(lineno, line, cptr);
3264 #if defined(YYBTYACC)
3266 start_requires_args(goal->name);
3278 for (i = 0; i < ntags; ++i)
3280 assert(tag_table[i]);
3292 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
3293 for (bp = first_symbol; bp; bp = bp->next)
3294 name_pool_size += strlen(bp->name) + 1;
3296 name_pool = TMALLOC(char, name_pool_size);
3297 NO_SPACE(name_pool);
3299 strcpy(name_pool, "$accept");
3300 strcpy(name_pool + 8, "$end");
3302 for (bp = first_symbol; bp; bp = bp->next)
3306 while ((*t++ = *s++) != 0)
3318 if (goal->class == UNKNOWN)
3319 undefined_goal(goal->name);
3321 for (bp = first_symbol; bp; bp = bp->next)
3323 if (bp->class == UNKNOWN)
3325 undefined_symbol_warning(bp->name);
3332 protect_string(char *src, char **des)
3345 if ('\\' == *s || '"' == *s)
3351 *des = d = TMALLOC(char, len);
3357 if ('\\' == *s || '"' == *s)
3371 #if defined(YYBTYACC)
3372 Value_t max_tok_pval;
3377 for (bp = first_symbol; bp; bp = bp->next)
3380 if (bp->class == TERM)
3383 start_symbol = (Value_t)ntokens;
3384 nvars = (Value_t)(nsyms - ntokens);
3386 symbol_name = TMALLOC(char *, nsyms);
3387 NO_SPACE(symbol_name);
3389 symbol_value = TMALLOC(Value_t, nsyms);
3390 NO_SPACE(symbol_value);
3392 symbol_prec = TMALLOC(Value_t, nsyms);
3393 NO_SPACE(symbol_prec);
3395 symbol_assoc = TMALLOC(char, nsyms);
3396 NO_SPACE(symbol_assoc);
3398 #if defined(YYBTYACC)
3399 symbol_pval = TMALLOC(Value_t, nsyms);
3400 NO_SPACE(symbol_pval);
3404 symbol_destructor = CALLOC(sizeof(char *), nsyms);
3405 NO_SPACE(symbol_destructor);
3407 symbol_type_tag = CALLOC(sizeof(char *), nsyms);
3408 NO_SPACE(symbol_type_tag);
3412 v = TMALLOC(bucket *, nsyms);
3416 v[start_symbol] = 0;
3419 j = (Value_t)(start_symbol + 1);
3420 for (bp = first_symbol; bp; bp = bp->next)
3422 if (bp->class == TERM)
3427 assert(i == ntokens && j == nsyms);
3429 for (i = 1; i < ntokens; ++i)
3432 goal->index = (Index_t)(start_symbol + 1);
3433 k = (Value_t)(start_symbol + 2);
3443 for (i = (Value_t)(start_symbol + 1); i < nsyms; ++i)
3453 for (i = 1; i < ntokens; ++i)
3458 for (j = k++; j > 0 && symbol_value[j - 1] > n; --j)
3459 symbol_value[j] = symbol_value[j - 1];
3460 symbol_value[j] = n;
3466 if (v[1]->value == UNDEFINED)
3471 for (i = 2; i < ntokens; ++i)
3473 if (v[i]->value == UNDEFINED)
3475 while (j < k && n == symbol_value[j])
3477 while (++j < k && n == symbol_value[j])
3486 symbol_name[0] = name_pool + 8;
3487 symbol_value[0] = 0;
3489 symbol_assoc[0] = TOKEN;
3490 #if defined(YYBTYACC)
3494 for (i = 1; i < ntokens; ++i)
3496 symbol_name[i] = v[i]->name;
3497 symbol_value[i] = v[i]->value;
3498 symbol_prec[i] = v[i]->prec;
3499 symbol_assoc[i] = v[i]->assoc;
3500 #if defined(YYBTYACC)
3501 symbol_pval[i] = v[i]->value;
3502 if (symbol_pval[i] > max_tok_pval)
3503 max_tok_pval = symbol_pval[i];
3506 symbol_destructor[i] = v[i]->destructor;
3507 symbol_type_tag[i] = v[i]->tag;
3511 symbol_name[start_symbol] = name_pool;
3512 symbol_value[start_symbol] = -1;
3513 symbol_prec[start_symbol] = 0;
3514 symbol_assoc[start_symbol] = TOKEN;
3515 #if defined(YYBTYACC)
3516 symbol_pval[start_symbol] = (Value_t)(max_tok_pval + 1);
3518 for (++i; i < nsyms; ++i)
3521 symbol_name[k] = v[i]->name;
3522 symbol_value[k] = v[i]->value;
3523 symbol_prec[k] = v[i]->prec;
3524 symbol_assoc[k] = v[i]->assoc;
3525 #if defined(YYBTYACC)
3526 symbol_pval[k] = (Value_t)((max_tok_pval + 1) + v[i]->value + 1);
3529 symbol_destructor[k] = v[i]->destructor;
3530 symbol_type_tag[k] = v[i]->tag;
3537 symbol_pname = TMALLOC(char *, nsyms);
3538 NO_SPACE(symbol_pname);
3540 for (i = 0; i < nsyms; ++i)
3541 protect_string(symbol_name[i], &(symbol_pname[i]));
3555 ritem = TMALLOC(Value_t, nitems);
3558 rlhs = TMALLOC(Value_t, nrules);
3561 rrhs = TMALLOC(Value_t, nrules + 1);
3564 rprec = TREALLOC(Value_t, rprec, nrules);
3567 rassoc = TREALLOC(Assoc_t, rassoc, nrules);
3571 ritem[1] = goal->index;
3576 rlhs[2] = start_symbol;
3582 for (i = 3; i < nrules; ++i)
3584 #if defined(YYBTYACC)
3585 if (plhs[i]->args > 0)
3587 if (plhs[i]->argnames)
3589 FREE(plhs[i]->argnames);
3590 plhs[i]->argnames = NULL;
3592 if (plhs[i]->argtags)
3594 FREE(plhs[i]->argtags);
3595 plhs[i]->argtags = NULL;
3598 #endif /* defined(YYBTYACC) */
3599 rlhs[i] = plhs[i]->index;
3605 ritem[j] = pitem[j]->index;
3606 if (pitem[j]->class == TERM)
3608 prec2 = pitem[j]->prec;
3609 assoc = pitem[j]->assoc;
3613 ritem[j] = (Value_t)-i;
3615 if (rprec[i] == UNDEFINED)
3625 #if defined(YYBTYACC)
3634 size_t j, spacing = 0;
3635 FILE *f = verbose_file;
3641 for (i = 2; i < nrules; ++i)
3643 if (rlhs[i] != rlhs[i - 1])
3647 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
3648 spacing = strlen(symbol_name[rlhs[i]]) + 1;
3652 fprintf(f, "%4d ", i - 2);
3659 while (ritem[k] >= 0)
3661 fprintf(f, " %s", symbol_name[ritem[k]]);
3669 #if defined(YYBTYACC)
3671 finalize_destructors(void)
3677 for (i = 2; i < nsyms; ++i)
3679 tag = symbol_type_tag[i];
3680 if (symbol_destructor[i] == NULL)
3683 { /* use <> destructor, if there is one */
3684 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3686 symbol_destructor[i] = TMALLOC(char,
3687 strlen(bp->destructor) + 1);
3688 NO_SPACE(symbol_destructor[i]);
3689 strcpy(symbol_destructor[i], bp->destructor);
3693 { /* use type destructor for this tag, if there is one */
3694 bp = lookup_type_destructor(tag);
3695 if (bp->destructor != NULL)
3697 symbol_destructor[i] = TMALLOC(char,
3698 strlen(bp->destructor) + 1);
3699 NO_SPACE(symbol_destructor[i]);
3700 strcpy(symbol_destructor[i], bp->destructor);
3703 { /* use <*> destructor, if there is one */
3704 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3705 /* replace "$$" with "(*val).tag" in destructor code */
3706 symbol_destructor[i]
3707 = process_destructor_XX(bp->destructor, tag);
3712 { /* replace "$$" with "(*val)[.tag]" in destructor code */
3713 symbol_destructor[i]
3714 = process_destructor_XX(symbol_destructor[i], tag);
3717 /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */
3718 DO_FREE(symbol_type_tag); /* no longer needed */
3719 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3722 /* 'bp->tag' is a static value, don't free */
3723 FREE(bp->destructor);
3726 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3729 /* 'bp->tag' is a static value, don't free */
3730 FREE(bp->destructor);
3733 if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL)
3740 /* 'bp->tag' freed by 'free_tags()' */
3741 FREE(bp->destructor);
3746 #endif /* defined(YYBTYACC) */
3751 write_section(code_file, banner);
3752 create_symbol_table();
3753 read_declarations();
3755 free_symbol_table();
3762 #if defined(YYBTYACC)
3764 finalize_destructors();
3771 free_declarations(param *list)
3775 param *next = list->next;
3788 lex_param = free_declarations(lex_param);
3789 parse_param = free_declarations(parse_param);
3799 DO_FREE(symbol_name);
3800 DO_FREE(symbol_prec);
3801 DO_FREE(symbol_assoc);
3802 DO_FREE(symbol_value);
3803 #if defined(YYBTYACC)
3804 DO_FREE(symbol_pval);
3805 DO_FREE(symbol_destructor);
3806 DO_FREE(symbol_type_tag);