1 /* $Id: reader.c,v 1.58 2014/10/06 22:15:08 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);
30 static int cinc, cache_size;
33 static int tagmax, havetags;
34 static char **tag_table;
44 static char last_was_action;
47 static bucket **pitem;
52 static size_t name_pool_size;
53 static char *name_pool;
55 char line_format[] = "#line %d \"%s\"\n";
61 int destructor = 0; /* =1 if at least one %destructor */
63 static bucket *default_destructor[3] =
66 #define UNTYPED_DEFAULT 0
67 #define TYPED_DEFAULT 1
68 #define TYPE_SPECIFIED 2
71 lookup_type_destructor(char *tag)
73 const char fmt[] = "%.*s destructor";
74 char name[1024] = "\0";
75 bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED];
77 while ((bp = *bpp) != NULL)
84 sprintf(name, fmt, (int)(sizeof(name) - sizeof(fmt)), tag);
85 *bpp = bp = make_bucket(name);
90 #endif /* defined(YYBTYACC) */
96 if (cinc >= cache_size)
99 cache = TREALLOC(char, cache, cache_size);
102 cache[cinc] = (char)c;
109 FILE *f = input_file;
113 if (saw_eof || (c = getc(f)) == EOF)
125 if (line == 0 || linesize != (LINESIZE + 1))
129 linesize = LINESIZE + 1;
130 line = TMALLOC(char, linesize);
141 if ((i + 3) >= linesize)
143 linesize += LINESIZE;
144 line = TREALLOC(char, line, linesize);
170 p = TMALLOC(char, s - line + 1);
175 while ((*t++ = *s++) != '\n')
185 int st_lineno = lineno;
186 char *st_line = dup_line();
187 char *st_cptr = st_line + (cptr - line);
192 if (*s == '*' && s[1] == '/')
202 unterminated_comment(st_lineno, st_line, st_cptr);
235 else if (s[1] == '/')
260 switch (ch = next_inline())
287 static struct keyword
293 { "binary", NONASSOC },
294 #if defined(YYBTYACC)
295 { "destructor", DESTRUCTOR },
297 { "expect", EXPECT },
298 { "expect-rr", EXPECT_RR },
301 { "lex-param", LEX_PARAM },
302 #if defined(YYBTYACC)
303 { "locations", LOCATIONS },
305 { "nonassoc", NONASSOC },
306 { "parse-param", PARSE_PARAM },
307 { "pure-parser", PURE_PARSER },
312 { "token-table", TOKEN_TABLE },
315 { "yacc", POSIX_YACC },
320 compare_keys(const void *a, const void *b)
322 const struct keyword *p = (const struct keyword *)a;
323 const struct keyword *q = (const struct keyword *)b;
324 return strcmp(p->name, q->name);
355 /* treat keywords spelled with '_' as if it were '-' */
366 if ((key = bsearch(cache, keywords,
367 sizeof(keywords) / sizeof(*key),
368 sizeof(*key), compare_keys)))
376 if (c == '%' || c == '\\')
387 syntax_error(lineno, line, t_cptr);
395 FILE *f = output_file;
401 syntax_error(lineno, line, cptr);
403 fprintf(f, "#ident \"");
423 copy_string(int quote)
425 struct mstring *temp = msnew();
427 int s_lineno = lineno;
428 char *s_line = dup_line();
429 char *s_cptr = s_line + (cptr - line - 1);
441 unterminated_string(s_lineno, s_line, s_cptr);
450 unterminated_string(s_lineno, s_line, s_cptr);
459 struct mstring *temp = msnew();
466 while ((c = *++cptr) != '\n')
469 if (c == '*' && cptr[1] == '/')
477 int c_lineno = lineno;
478 char *c_line = dup_line();
479 char *c_cptr = c_line + (cptr - line - 1);
487 if (c == '*' && *cptr == '/')
498 unterminated_comment(c_lineno, c_line, c_cptr);
510 int need_newline = 0;
511 int t_lineno = lineno;
512 char *t_line = dup_line();
513 char *t_cptr = t_line + (cptr - line - 2);
519 unterminated_text(t_lineno, t_line, t_cptr);
522 fprintf(f, line_format, lineno, input_file_name);
534 unterminated_text(t_lineno, t_line, t_cptr);
540 char *s = copy_string(c);
550 char *s = copy_comment();
577 puts_both(const char *s)
581 fputs(s, union_file);
597 int u_lineno = lineno;
598 char *u_line = dup_line();
599 char *u_cptr = u_line + (cptr - line - 6);
602 over_unionized(cptr - 6);
606 fprintf(text_file, line_format, lineno, input_file_name);
608 puts_both("#ifdef YYSTYPE\n");
609 puts_both("#undef YYSTYPE_IS_DECLARED\n");
610 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
611 puts_both("#endif\n");
612 puts_both("#ifndef YYSTYPE_IS_DECLARED\n");
613 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
614 puts_both("typedef union");
625 unterminated_union(u_lineno, u_line, u_cptr);
635 puts_both(" YYSTYPE;\n");
636 puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n");
645 char *s = copy_string(c);
653 char *s = copy_comment();
665 after_blanks(char *s)
667 while (*s != '\0' && isspace(UCH(*s)))
673 * Trim leading/trailing blanks, and collapse multiple embedded blanks to a
674 * single space. Return index to last character in the buffer.
677 trim_blanks(char *buffer)
682 char *s = after_blanks(d);
684 while ((*d++ = *s++) != '\0')
690 while ((--d != buffer) && isspace(UCH(*d)))
693 for (s = d = buffer; (*d++ = *s++) != '\0';)
695 if (isspace(UCH(*s)))
698 while (isspace(UCH(*s)))
707 return (int)strlen(buffer) - 1;
711 * Scan forward in the current line-buffer looking for a right-curly bracket.
713 * Parameters begin with a left-curly bracket, and continue until there are no
714 * more interesting characters after the last right-curly bracket on the
715 * current line. Bison documents parameters as separated like this:
716 * {type param1} {type2 param2}
717 * but also accepts commas (although some versions of bison mishandle this)
718 * {type param1, type2 param2}
728 switch (next_inline())
747 save_param(int k, char *buffer, int name, int type2)
751 p = TMALLOC(param, 1);
754 p->type2 = strdup(buffer + type2);
756 buffer[type2] = '\0';
757 (void)trim_blanks(p->type2);
759 p->name = strdup(buffer + name);
762 (void)trim_blanks(p->name);
764 p->type = strdup(buffer);
766 (void)trim_blanks(p->type);
790 * Keep a linked list of parameters. This may be multi-line, if the trailing
791 * right-curly bracket is absent.
802 int st_lineno = lineno;
836 if ((curly == 1) && (cptr == line))
846 if (curly == 0 && !isspace(UCH(c)))
854 buf_size = (size_t) linesize;
855 buf = TMALLOC(char, buf_size);
863 buf_size += (size_t) linesize;
864 buf = TREALLOC(char, buf, buf_size);
869 if ((state == 2) && (c == L_CURL))
873 else if ((state == 2) && isspace(UCH(c)))
877 else if ((c != L_CURL) && (c != R_CURL))
884 while (curly < 2 || more_curly());
897 i = trim_blanks(buf);
902 char *parms = (comma + 1);
903 comma = strchr(parms, ',');
907 (void)trim_blanks(parms);
908 i = (int)strlen(parms) - 1;
917 while (i >= 0 && level > 0 && parms[i] != '[')
921 else if (parms[i] == '[')
934 while (i > 0 && (isalnum(UCH(parms[i])) || UCH(parms[i]) == '_'))
937 if (!isspace(UCH(parms[i])) && parms[i] != '*')
942 save_param(k, parms, name, type2);
950 syntax_error(lineno, line, cptr);
956 if (c >= '0' && c <= '9')
958 if (c >= 'A' && c <= 'F')
959 return (c - 'A' + 10);
960 if (c >= 'a' && c <= 'f')
961 return (c - 'a' + 10);
973 int s_lineno = lineno;
974 char *s_line = dup_line();
975 char *s_cptr = s_line + (cptr - line);
985 unterminated_string(s_lineno, s_line, s_cptr);
988 char *c_cptr = cptr - 1;
996 unterminated_string(s_lineno, s_line, s_cptr);
1011 n = (n << 3) + (c - '0');
1015 n = (n << 3) + (c - '0');
1020 illegal_character(c_cptr);
1027 if (n < 0 || n >= 16)
1028 illegal_character(c_cptr);
1033 if (i < 0 || i >= 16)
1038 illegal_character(c_cptr);
1071 s = TMALLOC(char, n);
1074 for (i = 0; i < n; ++i)
1083 for (i = 0; i < n; ++i)
1086 if (c == '\\' || c == cache[0])
1091 else if (isprint(c))
1120 cachec(((c >> 6) & 7) + '0');
1121 cachec(((c >> 3) & 7) + '0');
1122 cachec((c & 7) + '0');
1136 if (n == 1 && bp->value == UNDEFINED)
1137 bp->value = UCH(*s);
1144 is_reserved(char *name)
1148 if (strcmp(name, ".") == 0 ||
1149 strcmp(name, "$accept") == 0 ||
1150 strcmp(name, "$end") == 0)
1153 if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2])))
1156 while (isdigit(UCH(*s)))
1171 for (c = *cptr; IS_IDENT(c); c = *++cptr)
1175 if (is_reserved(cache))
1176 used_reserved(cache);
1178 return (lookup(cache));
1188 for (c = *cptr; isdigit(c); c = *++cptr)
1189 n = (Value_t) (10 * n + (c - '0'));
1195 cache_tag(char *tag, size_t len)
1200 for (i = 0; i < ntags; ++i)
1202 if (strncmp(tag, tag_table[i], len) == 0 &&
1203 tag_table[i][len] == NUL)
1204 return (tag_table[i]);
1207 if (ntags >= tagmax)
1212 ? TREALLOC(char *, tag_table, tagmax)
1213 : TMALLOC(char *, tagmax));
1214 NO_SPACE(tag_table);
1217 s = TMALLOC(char, len + 1);
1220 strncpy(s, tag, len);
1222 tag_table[ntags++] = s;
1230 int t_lineno = lineno;
1231 char *t_line = dup_line();
1232 char *t_cptr = t_line + (cptr - line);
1238 if (!isalpha(c) && c != '_' && c != '$')
1239 illegal_tag(t_lineno, t_line, t_cptr);
1247 while (IS_IDENT(c));
1254 illegal_tag(t_lineno, t_line, t_cptr);
1259 return cache_tag(cache, (size_t) cinc);
1262 #if defined(YYBTYACC)
1268 while (isalnum(*cptr) || *cptr == '_' || *cptr == '$')
1270 return cache_tag(b, (size_t) (cptr - b));
1275 declare_tokens(int assoc)
1298 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1300 else if (c == '\'' || c == '"')
1306 tokenized_start(bp->name);
1311 if (bp->tag && tag != bp->tag)
1312 retyped_warning(bp->name);
1318 if (bp->prec && prec != bp->prec)
1319 reprec_warning(bp->name);
1320 bp->assoc = (Assoc_t) assoc;
1330 value = get_number();
1331 if (bp->value != UNDEFINED && value != bp->value)
1332 revalued_warning(bp->name);
1342 * %expect requires special handling
1343 * as it really isn't part of the yacc
1344 * grammar only a flag for yacc proper.
1347 declare_expect(int assoc)
1351 if (assoc != EXPECT && assoc != EXPECT_RR)
1355 * Stay away from nextc - doesn't
1356 * detect EOL and will read to EOF.
1366 if (assoc == EXPECT)
1367 SRexpect = get_number();
1369 RRexpect = get_number();
1373 * Looking for number before EOL.
1374 * Spaces, tabs, and numbers are ok,
1375 * words, punc., etc. are syntax errors.
1377 else if (c == '\n' || isalpha(c) || !isspace(c))
1379 syntax_error(lineno, line, cptr);
1390 #if defined(YYBTYACC)
1392 declare_argtypes(bucket *bp)
1394 char *tags[MAXARGS];
1398 retyped_warning(bp->name);
1399 cptr++; /* skip open paren */
1406 syntax_error(lineno, line, cptr);
1407 tags[args++] = get_tag();
1414 cptr++; /* skip close paren */
1416 bp->argnames = TMALLOC(char *, args);
1417 NO_SPACE(bp->argnames);
1418 bp->argtags = CALLOC(sizeof(char *), args + 1);
1419 NO_SPACE(bp->argtags);
1422 bp->argtags[args] = tags[args];
1423 bp->argnames[args] = NULL;
1446 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1449 #if defined(YYBTYACC)
1450 if (nextc() == L_PAREN)
1451 declare_argtypes(bp);
1456 else if (c == '\'' || c == '"')
1459 #if defined(YYBTYACC)
1468 if (bp->tag && tag != bp->tag)
1469 retyped_warning(bp->name);
1484 if (!isalpha(c) && c != '_' && c != '.' && c != '$')
1485 syntax_error(lineno, line, cptr);
1487 if (bp->class == TERM)
1488 terminal_start(bp->name);
1489 if (goal && goal != bp)
1490 restarted_warning();
1495 read_declarations(void)
1500 cache = TMALLOC(char, cache_size);
1509 syntax_error(lineno, line, cptr);
1510 switch (k = keyword())
1560 #if defined(YYBTYACC)
1572 /* noop for bison compatibility. byacc is already designed to be posix
1573 * yacc compatible. */
1580 initialize_grammar(void)
1585 pitem = TMALLOC(bucket *, maxitems);
1596 plhs = TMALLOC(bucket *, maxrules);
1603 rprec = TMALLOC(Value_t, maxrules);
1610 rassoc = TMALLOC(Assoc_t, maxrules);
1622 pitem = TREALLOC(bucket *, pitem, maxitems);
1631 plhs = TREALLOC(bucket *, plhs, maxrules);
1634 rprec = TREALLOC(Value_t, rprec, maxrules);
1637 rassoc = TREALLOC(Assoc_t, rassoc, maxrules);
1641 /* set immediately prior to where copy_args() could be called, and incremented by
1642 the various routines that will rescan the argument list as appropriate */
1643 static int rescan_lineno;
1644 #if defined(YYBTYACC)
1647 copy_args(int *alen)
1649 struct mstring *s = msnew();
1650 int depth = 0, len = 1;
1652 int a_lineno = lineno;
1653 char *a_line = dup_line();
1654 char *a_cptr = a_line + (cptr - line - 1);
1656 while ((c = *cptr++) != R_PAREN || depth || quote)
1658 if (c == ',' && !quote && !depth)
1671 unterminated_string(a_lineno, a_line, a_cptr);
1673 unterminated_arglist(a_lineno, a_line, a_cptr);
1690 else if (c == R_PAREN)
1692 else if (c == '\"' || c == '\'')
1703 parse_id(char *p, char **save)
1710 if (!isalpha(*p) && *p != '_')
1713 while (isalnum(*p) || *p == '_' || *p == '$')
1717 *save = cache_tag(b, (size_t) (p - b));
1723 parse_int(char *p, int *save)
1725 int neg = 0, val = 0;
1738 val = val * 10 + *p++ - '0';
1747 parse_arginfo(bucket *a, char *args, int argslen)
1749 char *p = args, *tmp;
1754 if (a->args != argslen)
1755 arg_number_disagree_warning(rescan_lineno, a->name);
1760 if ((a->args = argslen) == 0)
1762 a->argnames = TMALLOC(char *, argslen);
1763 NO_SPACE(a->argnames);
1764 a->argtags = TMALLOC(char *, argslen);
1765 NO_SPACE(a->argtags);
1769 for (i = 0; i < argslen; i++)
1782 if (!(p = parse_id(p + 1, &tmp)))
1791 if (a->argtags[i] != tmp)
1792 arg_type_disagree_warning(rescan_lineno, i + 1, a->name);
1795 a->argtags[i] = tmp;
1798 a->argtags[i] = NULL;
1799 if (!(p = parse_id(p, &a->argnames[i])))
1811 compile_arg(char **theptr, char *yyvaltag)
1814 struct mstring *c = msnew();
1816 Value_t *offsets = NULL, maxoffset;
1821 for (i = nitems - 1; pitem[i]; --i)
1824 if (pitem[i]->class != ARGUMENT)
1829 offsets = TMALLOC(Value_t, maxoffset + 1);
1832 for (j = 0, i++; i < nitems; i++)
1833 if (pitem[i]->class != ARGUMENT)
1834 offsets[++j] = (Value_t) (i - nitems + 1);
1836 rhs = pitem + nitems - 1;
1839 msprintf(c, "yyval.%s = ", yyvaltag);
1841 msprintf(c, "yyval = ");
1848 if (!(p = parse_id(++p, &tag)) || *p++ != '>')
1849 illegal_tag(rescan_lineno, NULL, NULL);
1850 if (isdigit(*p) || *p == '-')
1853 if (!(p = parse_int(p, &val)))
1854 dollar_error(rescan_lineno, NULL, NULL);
1857 else if (val > maxoffset)
1859 dollar_warning(rescan_lineno, val);
1860 i = val - maxoffset;
1862 else if (maxoffset > 0)
1865 if (!tag && !(tag = rhs[i]->tag) && havetags)
1866 untyped_rhs(val, rhs[i]->name);
1868 msprintf(c, "yystack.l_mark[%d]", i);
1870 msprintf(c, ".%s", tag);
1874 else if (isalpha(*p) || *p == '_')
1877 if (!(p = parse_id(p, &arg)))
1878 dollar_error(rescan_lineno, NULL, NULL);
1879 for (i = plhs[nrules]->args - 1; i >= 0; i--)
1880 if (arg == plhs[nrules]->argnames[i])
1883 unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL);
1885 tag = plhs[nrules]->argtags[i];
1886 msprintf(c, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1
1889 msprintf(c, ".%s", tag);
1891 untyped_arg_warning(rescan_lineno, "$", arg);
1894 dollar_error(rescan_lineno, NULL, NULL);
1898 at_error(rescan_lineno, NULL, NULL);
1913 #define ARG_CACHE_SIZE 1024
1914 static struct arg_cache
1916 struct arg_cache *next;
1920 *arg_cache[ARG_CACHE_SIZE];
1923 lookup_arg_cache(char *code)
1925 struct arg_cache *entry;
1927 entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE];
1930 if (!strnscmp(entry->code, code))
1932 entry = entry->next;
1938 insert_arg_cache(char *code, int rule)
1940 struct arg_cache *entry = NEW(struct arg_cache);
1944 i = strnshash(code) % ARG_CACHE_SIZE;
1947 entry->next = arg_cache[i];
1948 arg_cache[i] = entry;
1952 clean_arg_cache(void)
1954 struct arg_cache *e, *t;
1957 for (i = 0; i < ARG_CACHE_SIZE; i++)
1959 for (e = arg_cache[i]; (t = e); e = e->next, FREE(t))
1961 arg_cache[i] = NULL;
1967 advance_to_start(void)
1973 #if defined(YYBTYACC)
1998 syntax_error(lineno, line, s_cptr);
2003 if (!isalpha(c) && c != '_' && c != '.' && c != '_')
2004 syntax_error(lineno, line, cptr);
2008 if (bp->class == TERM)
2009 terminal_start(bp->name);
2017 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2018 #if defined(YYBTYACC)
2022 args = copy_args(&argslen);
2028 syntax_error(lineno, line, cptr);
2029 start_rule(bp, s_lineno);
2030 #if defined(YYBTYACC)
2031 parse_arginfo(bp, args, argslen);
2037 start_rule(bucket *bp, int s_lineno)
2039 if (bp->class == TERM)
2040 terminal_lhs(s_lineno);
2041 bp->class = NONTERM;
2044 if (nrules >= maxrules)
2047 rprec[nrules] = UNDEFINED;
2048 rassoc[nrules] = TOKEN;
2056 if (!last_was_action && plhs[nrules]->tag)
2058 if (pitem[nitems - 1])
2060 for (i = nitems - 1; (i > 0) && pitem[i]; --i)
2062 if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag)
2063 default_action_warning();
2067 default_action_warning();
2071 last_was_action = 0;
2072 if (nitems >= maxitems)
2080 insert_empty_rule(void)
2085 sprintf(cache, "$$%d", ++gensym);
2086 bp = make_bucket(cache);
2087 last_symbol->next = bp;
2089 bp->tag = plhs[nrules]->tag;
2091 #if defined(YYBTYACC)
2095 nitems = (Value_t) (nitems + 2);
2096 if (nitems > maxitems)
2098 bpp = pitem + nitems - 1;
2100 while ((bpp[0] = bpp[-1]) != 0)
2103 if (++nrules >= maxrules)
2105 plhs[nrules] = plhs[nrules - 1];
2106 plhs[nrules - 1] = bp;
2107 rprec[nrules] = rprec[nrules - 1];
2108 rprec[nrules - 1] = 0;
2109 rassoc[nrules] = rassoc[nrules - 1];
2110 rassoc[nrules - 1] = TOKEN;
2113 #if defined(YYBTYACC)
2115 insert_arg_rule(char *arg, char *tag)
2117 int line_number = rescan_lineno;
2118 char *code = compile_arg(&arg, tag);
2119 int rule = lookup_arg_cache(code);
2120 FILE *f = action_file;
2125 insert_arg_cache(code, rule);
2126 fprintf(f, "case %d:\n", rule - 2);
2128 fprintf(f, line_format, line_number, input_file_name);
2129 fprintf(f, "%s;\n", code);
2130 fprintf(f, "break;\n");
2131 insert_empty_rule();
2132 plhs[rule]->tag = tag;
2133 plhs[rule]->class = ARGUMENT;
2137 if (++nitems > maxitems)
2139 pitem[nitems - 1] = plhs[rule];
2151 int s_lineno = lineno;
2152 #if defined(YYBTYACC)
2158 if (c == '\'' || c == '"')
2164 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2165 #if defined(YYBTYACC)
2169 args = copy_args(&argslen);
2177 start_rule(bp, s_lineno);
2178 #if defined(YYBTYACC)
2179 parse_arginfo(bp, args, argslen);
2185 if (last_was_action)
2186 insert_empty_rule();
2187 last_was_action = 0;
2189 #if defined(YYBTYACC)
2192 if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL)
2195 if (plhs[nrules]->args != bp->args)
2196 wrong_number_args_warning("default ", bp->name);
2197 for (i = bp->args - 1; i >= 0; i--)
2198 if (plhs[nrules]->argtags[i] != bp->argtags[i])
2199 wrong_type_for_arg_warning(i + 1, bp->name);
2201 else if (bp->args != argslen)
2202 wrong_number_args_warning("", bp->name);
2203 if (bp->args > 0 && argslen > 0)
2207 for (ap = args, i = 0; i < argslen; i++)
2208 ap = insert_arg_rule(ap, bp->argtags[i]);
2211 #endif /* defined(YYBTYACC) */
2213 if (++nitems > maxitems)
2215 pitem[nitems - 1] = bp;
2224 #if defined(YYBTYACC)
2225 int trialaction = 0;
2229 FILE *f = action_file;
2230 int a_lineno = lineno;
2231 char *a_line = dup_line();
2232 char *a_cptr = a_line + (cptr - line);
2233 Value_t *offsets = NULL, maxoffset;
2236 if (last_was_action)
2237 insert_empty_rule();
2238 last_was_action = 1;
2240 fprintf(f, "case %d:\n", nrules - 2);
2241 #if defined(YYBTYACC)
2244 if (*cptr != L_BRAC)
2245 fprintf(f, " if (!yytrial)\n");
2251 fprintf(f, line_format, lineno, input_file_name);
2255 /* avoid putting curly-braces in first column, to ease editing */
2256 if (*after_blanks(cptr) == L_CURL)
2259 cptr = after_blanks(cptr);
2264 for (i = nitems - 1; pitem[i]; --i)
2267 if (pitem[i]->class != ARGUMENT)
2272 offsets = TMALLOC(Value_t, maxoffset + 1);
2275 for (j = 0, i++; i < nitems; i++)
2277 if (pitem[i]->class != ARGUMENT)
2279 offsets[++j] = (Value_t) (i - nitems + 1);
2283 rhs = pitem + nitems - 1;
2292 int d_lineno = lineno;
2293 char *d_line = dup_line();
2294 char *d_cptr = d_line + (cptr - line);
2301 fprintf(f, "yyval.%s", tag);
2306 else if (isdigit(c))
2310 fprintf(f, "yystack.l_mark[%d].%s", -n, tag);
2311 else if (i > maxoffset)
2313 dollar_warning(d_lineno, i);
2314 fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag);
2317 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2321 else if (c == '-' && isdigit(UCH(cptr[1])))
2324 i = -get_number() - n;
2325 fprintf(f, "yystack.l_mark[%d].%s", i, tag);
2329 #if defined(YYBTYACC)
2330 else if (isalpha(c) || c == '_')
2332 char *arg = scan_id();
2333 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2334 if (arg == plhs[nrules]->argnames[i])
2337 unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr);
2338 fprintf(f, "yystack.l_mark[%d].%s", i - plhs[nrules]->args +
2345 dollar_error(d_lineno, d_line, d_cptr);
2347 else if (cptr[1] == '$')
2351 tag = plhs[nrules]->tag;
2354 fprintf(f, "yyval.%s", tag);
2357 fprintf(f, "yyval");
2359 #if defined(YYBTYACC)
2364 else if (isdigit(UCH(cptr[1])))
2368 if (havetags && offsets)
2370 if (i <= 0 || i > maxoffset)
2372 tag = rhs[offsets[i]]->tag;
2374 untyped_rhs(i, rhs[offsets[i]]->name);
2375 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2380 fprintf(f, "yystack.l_mark[%d]", -n);
2381 else if (i > maxoffset)
2383 dollar_warning(lineno, i);
2384 fprintf(f, "yystack.l_mark[%d]", i - maxoffset);
2387 fprintf(f, "yystack.l_mark[%d]", offsets[i]);
2391 else if (cptr[1] == '-')
2397 fprintf(f, "yystack.l_mark[%d]", -i - n);
2400 #if defined(YYBTYACC)
2401 else if (isalpha(cptr[1]) || cptr[1] == '_')
2406 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2407 if (arg == plhs[nrules]->argnames[i])
2410 unknown_arg_warning(lineno, "$", arg, line, cptr);
2411 tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]);
2412 fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n);
2414 fprintf(f, ".%s", tag);
2416 untyped_arg_warning(lineno, "$", arg);
2421 #if defined(YYBTYACC)
2426 int l_lineno = lineno;
2427 char *l_line = dup_line();
2428 char *l_cptr = l_line + (cptr - line);
2429 syntax_error(l_lineno, l_line, l_cptr);
2433 fprintf(f, "yyloc");
2437 else if (isdigit(UCH(cptr[1])))
2442 fprintf(f, "yystack.p_mark[%d]", -n);
2443 else if (i > maxoffset)
2445 at_warning(lineno, i);
2446 fprintf(f, "yystack.p_mark[%d]", i - maxoffset);
2449 fprintf(f, "yystack.p_mark[%d]", offsets[i]);
2454 if (isalpha(c) || c == '_' || c == '$')
2461 while (isalnum(c) || c == '_' || c == '$');
2465 #if defined(YYBTYACC)
2468 if (trialaction && c == L_BRAC && depth == 0)
2474 if (trialaction && c == R_BRAC && depth == 1)
2479 if (c == L_BRAC && !haveyyval)
2483 if (c == L_CURL && !haveyyval)
2485 fprintf(f, " if (!yytrial)\n");
2487 fprintf(f, line_format, lineno, input_file_name);
2491 fprintf(f, "\nbreak;\n");
2506 unterminated_action(a_lineno, a_line, a_cptr);
2511 fprintf(f, "\nbreak;\n");
2517 #if defined(YYBTYACC)
2536 #if defined(YYBTYACC)
2540 if (c == L_BRAC && !haveyyval)
2545 if (c == L_CURL && !haveyyval)
2547 fprintf(f, " if (!yytrial)\n");
2549 fprintf(f, line_format, lineno, input_file_name);
2554 fprintf(f, "\nbreak;\n");
2563 char *s = copy_string(c);
2571 char *s = copy_comment();
2582 #if defined(YYBTYACC)
2584 copy_destructor(void)
2590 struct mstring *destructor_text = msnew();
2597 msprintf(destructor_text, line_format, lineno, input_file_name);
2599 cptr = after_blanks(cptr);
2600 if (*cptr == L_CURL)
2601 /* avoid putting curly-braces in first column, to ease editing */
2602 mputc(destructor_text, '\t');
2604 syntax_error(lineno, line, cptr);
2607 a_line = dup_line();
2608 a_cptr = a_line + (cptr - line);
2617 int d_lineno = lineno;
2618 char *d_line = dup_line();
2619 char *d_cptr = d_line + (cptr - line);
2626 msprintf(destructor_text, "(*val).%s", tag);
2632 dollar_error(d_lineno, d_line, d_cptr);
2634 else if (cptr[1] == '$')
2636 /* process '$$' later; replacement is context dependent */
2637 msprintf(destructor_text, "$$");
2642 if (c == '@' && cptr[1] == '$')
2646 int l_lineno = lineno;
2647 char *l_line = dup_line();
2648 char *l_cptr = l_line + (cptr - line);
2649 syntax_error(l_lineno, l_line, l_cptr);
2651 msprintf(destructor_text, "(*loc)");
2655 if (isalpha(c) || c == '_' || c == '$')
2659 mputc(destructor_text, c);
2662 while (isalnum(c) || c == '_' || c == '$');
2666 mputc(destructor_text, c);
2673 unterminated_action(a_lineno, a_line, a_cptr);
2682 goto process_symbols;
2687 char *s = copy_string(c);
2688 msprintf(destructor_text, "%s", s);
2695 char *s = copy_comment();
2696 msprintf(destructor_text, "%s", s);
2705 code_text = msdone(destructor_text);
2714 { /* "no semantic type" default destructor */
2716 if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL)
2718 static char untyped_default[] = "<>";
2719 bp = make_bucket("untyped default");
2720 bp->tag = untyped_default;
2721 default_destructor[UNTYPED_DEFAULT] = bp;
2723 if (bp->destructor != NULL)
2724 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2726 /* replace "$$" with "(*val)" in destructor code */
2727 bp->destructor = process_destructor_XX(code_text, NULL);
2729 else if (cptr[1] == '*' && cptr[2] == '>')
2730 { /* "no per-symbol or per-type" default destructor */
2732 if ((bp = default_destructor[TYPED_DEFAULT]) == NULL)
2734 static char typed_default[] = "<*>";
2735 bp = make_bucket("typed default");
2736 bp->tag = typed_default;
2737 default_destructor[TYPED_DEFAULT] = bp;
2739 if (bp->destructor != NULL)
2740 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2743 /* postpone re-processing destructor $$s until end of grammar spec */
2744 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2745 NO_SPACE(bp->destructor);
2746 strcpy(bp->destructor, code_text);
2750 { /* "semantic type" default destructor */
2752 bp = lookup_type_destructor(tag);
2753 if (bp->destructor != NULL)
2754 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2756 /* replace "$$" with "(*val).tag" in destructor code */
2757 bp->destructor = process_destructor_XX(code_text, tag);
2760 else if (isalpha(c) || c == '_' || c == '.' || c == '$')
2761 { /* "symbol" destructor */
2763 if (bp->destructor != NULL)
2764 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2767 /* postpone re-processing destructor $$s until end of grammar spec */
2768 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2769 NO_SPACE(bp->destructor);
2770 strcpy(bp->destructor, code_text);
2781 process_destructor_XX(char *code, char *tag)
2786 struct mstring *new_code = msnew();
2787 char *codeptr = code;
2790 loop: /* step thru code */
2792 if (c == '$' && codeptr[1] == '$')
2796 msprintf(new_code, "(*val)");
2798 msprintf(new_code, "(*val).%s", tag);
2801 if (isalpha(c) || c == '_' || c == '$')
2808 while (isalnum(c) || c == '_' || c == '$');
2822 return msdone(new_code);
2850 if (c == '*' && *codeptr == '/')
2852 mputc(new_code, '/');
2864 #endif /* defined(YYBTYACC) */
2873 if (c == '%' || c == '\\')
2881 else if ((c == 'p' || c == 'P') &&
2882 ((c = cptr[2]) == 'r' || c == 'R') &&
2883 ((c = cptr[3]) == 'e' || c == 'E') &&
2884 ((c = cptr[4]) == 'c' || c == 'C') &&
2885 ((c = cptr[5], !IS_IDENT(c))))
2888 syntax_error(lineno, line, cptr);
2891 if (isalpha(c) || c == '_' || c == '.' || c == '$')
2893 else if (c == '\'' || c == '"')
2897 syntax_error(lineno, line, cptr);
2900 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
2903 rprec[nrules] = bp->prec;
2904 rassoc[nrules] = bp->assoc;
2913 initialize_grammar();
2928 #if defined(YYBTYACC)
2929 else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC))
2931 else if (c == L_CURL || c == '=')
2937 start_rule(plhs[nrules - 1], 0);
2946 syntax_error(lineno, line, cptr);
2949 #if defined(YYBTYACC)
2951 start_requires_args(goal->name);
2963 for (i = 0; i < ntags; ++i)
2965 assert(tag_table[i]);
2977 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
2978 for (bp = first_symbol; bp; bp = bp->next)
2979 name_pool_size += strlen(bp->name) + 1;
2981 name_pool = TMALLOC(char, name_pool_size);
2982 NO_SPACE(name_pool);
2984 strcpy(name_pool, "$accept");
2985 strcpy(name_pool + 8, "$end");
2987 for (bp = first_symbol; bp; bp = bp->next)
2991 while ((*t++ = *s++) != 0)
3003 if (goal->class == UNKNOWN)
3004 undefined_goal(goal->name);
3006 for (bp = first_symbol; bp; bp = bp->next)
3008 if (bp->class == UNKNOWN)
3010 undefined_symbol_warning(bp->name);
3017 protect_string(char *src, char **des)
3030 if ('\\' == *s || '"' == *s)
3036 *des = d = TMALLOC(char, len);
3042 if ('\\' == *s || '"' == *s)
3056 #if defined(YYBTYACC)
3057 Value_t max_tok_pval;
3062 for (bp = first_symbol; bp; bp = bp->next)
3065 if (bp->class == TERM)
3068 start_symbol = (Value_t) ntokens;
3069 nvars = (Value_t) (nsyms - ntokens);
3071 symbol_name = TMALLOC(char *, nsyms);
3072 NO_SPACE(symbol_name);
3074 symbol_value = TMALLOC(Value_t, nsyms);
3075 NO_SPACE(symbol_value);
3077 symbol_prec = TMALLOC(Value_t, nsyms);
3078 NO_SPACE(symbol_prec);
3080 symbol_assoc = TMALLOC(char, nsyms);
3081 NO_SPACE(symbol_assoc);
3083 #if defined(YYBTYACC)
3084 symbol_pval = TMALLOC(Value_t, nsyms);
3085 NO_SPACE(symbol_pval);
3089 symbol_destructor = CALLOC(sizeof(char *), nsyms);
3090 NO_SPACE(symbol_destructor);
3092 symbol_type_tag = CALLOC(sizeof(char *), nsyms);
3093 NO_SPACE(symbol_type_tag);
3097 v = TMALLOC(bucket *, nsyms);
3101 v[start_symbol] = 0;
3104 j = (Value_t) (start_symbol + 1);
3105 for (bp = first_symbol; bp; bp = bp->next)
3107 if (bp->class == TERM)
3112 assert(i == ntokens && j == nsyms);
3114 for (i = 1; i < ntokens; ++i)
3117 goal->index = (Index_t) (start_symbol + 1);
3118 k = (Value_t) (start_symbol + 2);
3128 for (i = (Value_t) (start_symbol + 1); i < nsyms; ++i)
3138 for (i = 1; i < ntokens; ++i)
3143 for (j = k++; j > 0 && symbol_value[j - 1] > n; --j)
3144 symbol_value[j] = symbol_value[j - 1];
3145 symbol_value[j] = n;
3151 if (v[1]->value == UNDEFINED)
3156 for (i = 2; i < ntokens; ++i)
3158 if (v[i]->value == UNDEFINED)
3160 while (j < k && n == symbol_value[j])
3162 while (++j < k && n == symbol_value[j])
3171 symbol_name[0] = name_pool + 8;
3172 symbol_value[0] = 0;
3174 symbol_assoc[0] = TOKEN;
3175 #if defined(YYBTYACC)
3179 for (i = 1; i < ntokens; ++i)
3181 symbol_name[i] = v[i]->name;
3182 symbol_value[i] = v[i]->value;
3183 symbol_prec[i] = v[i]->prec;
3184 symbol_assoc[i] = v[i]->assoc;
3185 #if defined(YYBTYACC)
3186 symbol_pval[i] = v[i]->value;
3187 if (symbol_pval[i] > max_tok_pval)
3188 max_tok_pval = symbol_pval[i];
3191 symbol_destructor[i] = v[i]->destructor;
3192 symbol_type_tag[i] = v[i]->tag;
3196 symbol_name[start_symbol] = name_pool;
3197 symbol_value[start_symbol] = -1;
3198 symbol_prec[start_symbol] = 0;
3199 symbol_assoc[start_symbol] = TOKEN;
3200 #if defined(YYBTYACC)
3201 symbol_pval[start_symbol] = (Value_t) (max_tok_pval + 1);
3203 for (++i; i < nsyms; ++i)
3206 symbol_name[k] = v[i]->name;
3207 symbol_value[k] = v[i]->value;
3208 symbol_prec[k] = v[i]->prec;
3209 symbol_assoc[k] = v[i]->assoc;
3210 #if defined(YYBTYACC)
3211 symbol_pval[k] = (Value_t) ((max_tok_pval + 1) + v[i]->value + 1);
3214 symbol_destructor[k] = v[i]->destructor;
3215 symbol_type_tag[k] = v[i]->tag;
3222 symbol_pname = TMALLOC(char *, nsyms);
3223 NO_SPACE(symbol_pname);
3225 for (i = 0; i < nsyms; ++i)
3226 protect_string(symbol_name[i], &(symbol_pname[i]));
3240 ritem = TMALLOC(Value_t, nitems);
3243 rlhs = TMALLOC(Value_t, nrules);
3246 rrhs = TMALLOC(Value_t, nrules + 1);
3249 rprec = TREALLOC(Value_t, rprec, nrules);
3252 rassoc = TREALLOC(Assoc_t, rassoc, nrules);
3256 ritem[1] = goal->index;
3261 rlhs[2] = start_symbol;
3267 for (i = 3; i < nrules; ++i)
3269 #if defined(YYBTYACC)
3270 if (plhs[i]->args > 0)
3272 if (plhs[i]->argnames)
3274 FREE(plhs[i]->argnames);
3275 plhs[i]->argnames = NULL;
3277 if (plhs[i]->argtags)
3279 FREE(plhs[i]->argtags);
3280 plhs[i]->argtags = NULL;
3283 #endif /* defined(YYBTYACC) */
3284 rlhs[i] = plhs[i]->index;
3290 ritem[j] = pitem[j]->index;
3291 if (pitem[j]->class == TERM)
3293 prec2 = pitem[j]->prec;
3294 assoc = pitem[j]->assoc;
3298 ritem[j] = (Value_t) - i;
3300 if (rprec[i] == UNDEFINED)
3310 #if defined(YYBTYACC)
3319 size_t j, spacing = 0;
3320 FILE *f = verbose_file;
3326 for (i = 2; i < nrules; ++i)
3328 if (rlhs[i] != rlhs[i - 1])
3332 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
3333 spacing = strlen(symbol_name[rlhs[i]]) + 1;
3337 fprintf(f, "%4d ", i - 2);
3344 while (ritem[k] >= 0)
3346 fprintf(f, " %s", symbol_name[ritem[k]]);
3354 #if defined(YYBTYACC)
3356 finalize_destructors(void)
3362 for (i = 2; i < nsyms; ++i)
3364 tag = symbol_type_tag[i];
3365 if (symbol_destructor[i] == NULL)
3368 { /* use <> destructor, if there is one */
3369 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3371 symbol_destructor[i] = TMALLOC(char,
3372 strlen(bp->destructor) + 1);
3373 NO_SPACE(symbol_destructor[i]);
3374 strcpy(symbol_destructor[i], bp->destructor);
3378 { /* use type destructor for this tag, if there is one */
3379 bp = lookup_type_destructor(tag);
3380 if (bp->destructor != NULL)
3382 symbol_destructor[i] = TMALLOC(char,
3383 strlen(bp->destructor) + 1);
3384 NO_SPACE(symbol_destructor[i]);
3385 strcpy(symbol_destructor[i], bp->destructor);
3388 { /* use <*> destructor, if there is one */
3389 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3390 /* replace "$$" with "(*val).tag" in destructor code */
3391 symbol_destructor[i]
3392 = process_destructor_XX(bp->destructor, tag);
3397 { /* replace "$$" with "(*val)[.tag]" in destructor code */
3398 symbol_destructor[i]
3399 = process_destructor_XX(symbol_destructor[i], tag);
3402 /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */
3403 DO_FREE(symbol_type_tag); /* no longer needed */
3404 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3407 /* 'bp->tag' is a static value, don't free */
3408 FREE(bp->destructor);
3411 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3414 /* 'bp->tag' is a static value, don't free */
3415 FREE(bp->destructor);
3418 if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL)
3425 /* 'bp->tag' freed by 'free_tags()' */
3426 FREE(bp->destructor);
3431 #endif /* defined(YYBTYACC) */
3436 write_section(code_file, banner);
3437 create_symbol_table();
3438 read_declarations();
3440 free_symbol_table();
3447 #if defined(YYBTYACC)
3449 finalize_destructors();
3456 free_declarations(param * list)
3460 param *next = list->next;
3473 lex_param = free_declarations(lex_param);
3474 parse_param = free_declarations(parse_param);
3484 DO_FREE(symbol_name);
3485 DO_FREE(symbol_prec);
3486 DO_FREE(symbol_assoc);
3487 DO_FREE(symbol_value);
3488 #if defined(YYBTYACC)
3489 DO_FREE(symbol_pval);
3490 DO_FREE(symbol_destructor);
3491 DO_FREE(symbol_type_tag);