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);
394 FILE *f = output_file;
400 syntax_error(lineno, line, cptr);
402 fprintf(f, "#ident \"");
422 copy_string(int quote)
424 struct mstring *temp = msnew();
426 int s_lineno = lineno;
427 char *s_line = dup_line();
428 char *s_cptr = s_line + (cptr - line - 1);
440 unterminated_string(s_lineno, s_line, s_cptr);
449 unterminated_string(s_lineno, s_line, s_cptr);
458 struct mstring *temp = msnew();
465 while ((c = *++cptr) != '\n')
468 if (c == '*' && cptr[1] == '/')
476 int c_lineno = lineno;
477 char *c_line = dup_line();
478 char *c_cptr = c_line + (cptr - line - 1);
486 if (c == '*' && *cptr == '/')
497 unterminated_comment(c_lineno, c_line, c_cptr);
509 int need_newline = 0;
510 int t_lineno = lineno;
511 char *t_line = dup_line();
512 char *t_cptr = t_line + (cptr - line - 2);
518 unterminated_text(t_lineno, t_line, t_cptr);
521 fprintf(f, line_format, lineno, input_file_name);
533 unterminated_text(t_lineno, t_line, t_cptr);
539 char *s = copy_string(c);
549 char *s = copy_comment();
576 puts_both(const char *s)
580 fputs(s, union_file);
596 int u_lineno = lineno;
597 char *u_line = dup_line();
598 char *u_cptr = u_line + (cptr - line - 6);
601 over_unionized(cptr - 6);
605 fprintf(text_file, line_format, lineno, input_file_name);
607 puts_both("#ifdef YYSTYPE\n");
608 puts_both("#undef YYSTYPE_IS_DECLARED\n");
609 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
610 puts_both("#endif\n");
611 puts_both("#ifndef YYSTYPE_IS_DECLARED\n");
612 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
613 puts_both("typedef union");
624 unterminated_union(u_lineno, u_line, u_cptr);
634 puts_both(" YYSTYPE;\n");
635 puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n");
644 char *s = copy_string(c);
652 char *s = copy_comment();
664 after_blanks(char *s)
666 while (*s != '\0' && isspace(UCH(*s)))
672 * Trim leading/trailing blanks, and collapse multiple embedded blanks to a
673 * single space. Return index to last character in the buffer.
676 trim_blanks(char *buffer)
681 char *s = after_blanks(d);
683 while ((*d++ = *s++) != '\0')
689 while ((--d != buffer) && isspace(UCH(*d)))
692 for (s = d = buffer; (*d++ = *s++) != '\0';)
694 if (isspace(UCH(*s)))
697 while (isspace(UCH(*s)))
706 return (int)strlen(buffer) - 1;
710 * Scan forward in the current line-buffer looking for a right-curly bracket.
712 * Parameters begin with a left-curly bracket, and continue until there are no
713 * more interesting characters after the last right-curly bracket on the
714 * current line. Bison documents parameters as separated like this:
715 * {type param1} {type2 param2}
716 * but also accepts commas (although some versions of bison mishandle this)
717 * {type param1, type2 param2}
727 switch (next_inline())
746 save_param(int k, char *buffer, int name, int type2)
750 p = TMALLOC(param, 1);
753 p->type2 = strdup(buffer + type2);
755 buffer[type2] = '\0';
756 (void)trim_blanks(p->type2);
758 p->name = strdup(buffer + name);
761 (void)trim_blanks(p->name);
763 p->type = strdup(buffer);
765 (void)trim_blanks(p->type);
789 * Keep a linked list of parameters. This may be multi-line, if the trailing
790 * right-curly bracket is absent.
801 int st_lineno = lineno;
835 if ((curly == 1) && (cptr == line))
845 if (curly == 0 && !isspace(UCH(c)))
853 buf_size = (size_t) linesize;
854 buf = TMALLOC(char, buf_size);
862 buf_size += (size_t) linesize;
863 buf = TREALLOC(char, buf, buf_size);
868 if ((state == 2) && (c == L_CURL))
872 else if ((state == 2) && isspace(UCH(c)))
876 else if ((c != L_CURL) && (c != R_CURL))
883 while (curly < 2 || more_curly());
896 i = trim_blanks(buf);
901 char *parms = (comma + 1);
902 comma = strchr(parms, ',');
906 (void)trim_blanks(parms);
907 i = (int)strlen(parms) - 1;
916 while (i >= 0 && level > 0 && parms[i] != '[')
920 else if (parms[i] == '[')
933 while (i > 0 && (isalnum(UCH(parms[i])) || UCH(parms[i]) == '_'))
936 if (!isspace(UCH(parms[i])) && parms[i] != '*')
941 save_param(k, parms, name, type2);
949 syntax_error(lineno, line, cptr);
955 if (c >= '0' && c <= '9')
957 if (c >= 'A' && c <= 'F')
958 return (c - 'A' + 10);
959 if (c >= 'a' && c <= 'f')
960 return (c - 'a' + 10);
972 int s_lineno = lineno;
973 char *s_line = dup_line();
974 char *s_cptr = s_line + (cptr - line);
984 unterminated_string(s_lineno, s_line, s_cptr);
987 char *c_cptr = cptr - 1;
995 unterminated_string(s_lineno, s_line, s_cptr);
1010 n = (n << 3) + (c - '0');
1014 n = (n << 3) + (c - '0');
1019 illegal_character(c_cptr);
1026 if (n < 0 || n >= 16)
1027 illegal_character(c_cptr);
1032 if (i < 0 || i >= 16)
1037 illegal_character(c_cptr);
1070 s = TMALLOC(char, n);
1073 for (i = 0; i < n; ++i)
1082 for (i = 0; i < n; ++i)
1085 if (c == '\\' || c == cache[0])
1090 else if (isprint(c))
1119 cachec(((c >> 6) & 7) + '0');
1120 cachec(((c >> 3) & 7) + '0');
1121 cachec((c & 7) + '0');
1135 if (n == 1 && bp->value == UNDEFINED)
1136 bp->value = UCH(*s);
1143 is_reserved(char *name)
1147 if (strcmp(name, ".") == 0 ||
1148 strcmp(name, "$accept") == 0 ||
1149 strcmp(name, "$end") == 0)
1152 if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2])))
1155 while (isdigit(UCH(*s)))
1170 for (c = *cptr; IS_IDENT(c); c = *++cptr)
1174 if (is_reserved(cache))
1175 used_reserved(cache);
1177 return (lookup(cache));
1187 for (c = *cptr; isdigit(c); c = *++cptr)
1188 n = (Value_t) (10 * n + (c - '0'));
1194 cache_tag(char *tag, size_t len)
1199 for (i = 0; i < ntags; ++i)
1201 if (strncmp(tag, tag_table[i], len) == 0 &&
1202 tag_table[i][len] == NUL)
1203 return (tag_table[i]);
1206 if (ntags >= tagmax)
1211 ? TREALLOC(char *, tag_table, tagmax)
1212 : TMALLOC(char *, tagmax));
1213 NO_SPACE(tag_table);
1216 s = TMALLOC(char, len + 1);
1219 strncpy(s, tag, len);
1221 tag_table[ntags++] = s;
1229 int t_lineno = lineno;
1230 char *t_line = dup_line();
1231 char *t_cptr = t_line + (cptr - line);
1237 if (!isalpha(c) && c != '_' && c != '$')
1238 illegal_tag(t_lineno, t_line, t_cptr);
1246 while (IS_IDENT(c));
1253 illegal_tag(t_lineno, t_line, t_cptr);
1258 return cache_tag(cache, (size_t) cinc);
1261 #if defined(YYBTYACC)
1267 while (isalnum(*cptr) || *cptr == '_' || *cptr == '$')
1269 return cache_tag(b, (size_t) (cptr - b));
1274 declare_tokens(int assoc)
1297 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1299 else if (c == '\'' || c == '"')
1305 tokenized_start(bp->name);
1310 if (bp->tag && tag != bp->tag)
1311 retyped_warning(bp->name);
1317 if (bp->prec && prec != bp->prec)
1318 reprec_warning(bp->name);
1319 bp->assoc = (Assoc_t) assoc;
1329 value = get_number();
1330 if (bp->value != UNDEFINED && value != bp->value)
1331 revalued_warning(bp->name);
1341 * %expect requires special handling
1342 * as it really isn't part of the yacc
1343 * grammar only a flag for yacc proper.
1346 declare_expect(int assoc)
1350 if (assoc != EXPECT && assoc != EXPECT_RR)
1354 * Stay away from nextc - doesn't
1355 * detect EOL and will read to EOF.
1365 if (assoc == EXPECT)
1366 SRexpect = get_number();
1368 RRexpect = get_number();
1372 * Looking for number before EOL.
1373 * Spaces, tabs, and numbers are ok,
1374 * words, punc., etc. are syntax errors.
1376 else if (c == '\n' || isalpha(c) || !isspace(c))
1378 syntax_error(lineno, line, cptr);
1389 #if defined(YYBTYACC)
1391 declare_argtypes(bucket *bp)
1393 char *tags[MAXARGS];
1397 retyped_warning(bp->name);
1398 cptr++; /* skip open paren */
1405 syntax_error(lineno, line, cptr);
1406 tags[args++] = get_tag();
1413 cptr++; /* skip close paren */
1415 bp->argnames = TMALLOC(char *, args);
1416 NO_SPACE(bp->argnames);
1417 bp->argtags = CALLOC(sizeof(char *), args + 1);
1418 NO_SPACE(bp->argtags);
1421 bp->argtags[args] = tags[args];
1422 bp->argnames[args] = NULL;
1445 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1448 #if defined(YYBTYACC)
1449 if (nextc() == L_PAREN)
1450 declare_argtypes(bp);
1455 else if (c == '\'' || c == '"')
1458 #if defined(YYBTYACC)
1467 if (bp->tag && tag != bp->tag)
1468 retyped_warning(bp->name);
1483 if (!isalpha(c) && c != '_' && c != '.' && c != '$')
1484 syntax_error(lineno, line, cptr);
1486 if (bp->class == TERM)
1487 terminal_start(bp->name);
1488 if (goal && goal != bp)
1489 restarted_warning();
1494 read_declarations(void)
1499 cache = TMALLOC(char, cache_size);
1508 syntax_error(lineno, line, cptr);
1509 switch (k = keyword())
1559 #if defined(YYBTYACC)
1571 /* noop for bison compatibility. byacc is already designed to be posix
1572 * yacc compatible. */
1579 initialize_grammar(void)
1584 pitem = TMALLOC(bucket *, maxitems);
1595 plhs = TMALLOC(bucket *, maxrules);
1602 rprec = TMALLOC(Value_t, maxrules);
1609 rassoc = TMALLOC(Assoc_t, maxrules);
1621 pitem = TREALLOC(bucket *, pitem, maxitems);
1630 plhs = TREALLOC(bucket *, plhs, maxrules);
1633 rprec = TREALLOC(Value_t, rprec, maxrules);
1636 rassoc = TREALLOC(Assoc_t, rassoc, maxrules);
1640 /* set immediately prior to where copy_args() could be called, and incremented by
1641 the various routines that will rescan the argument list as appropriate */
1642 static int rescan_lineno;
1643 #if defined(YYBTYACC)
1646 copy_args(int *alen)
1648 struct mstring *s = msnew();
1649 int depth = 0, len = 1;
1651 int a_lineno = lineno;
1652 char *a_line = dup_line();
1653 char *a_cptr = a_line + (cptr - line - 1);
1655 while ((c = *cptr++) != R_PAREN || depth || quote)
1657 if (c == ',' && !quote && !depth)
1670 unterminated_string(a_lineno, a_line, a_cptr);
1672 unterminated_arglist(a_lineno, a_line, a_cptr);
1689 else if (c == R_PAREN)
1691 else if (c == '\"' || c == '\'')
1702 parse_id(char *p, char **save)
1709 if (!isalpha(*p) && *p != '_')
1712 while (isalnum(*p) || *p == '_' || *p == '$')
1716 *save = cache_tag(b, (size_t) (p - b));
1722 parse_int(char *p, int *save)
1724 int neg = 0, val = 0;
1737 val = val * 10 + *p++ - '0';
1746 parse_arginfo(bucket *a, char *args, int argslen)
1748 char *p = args, *tmp;
1753 if (a->args != argslen)
1754 arg_number_disagree_warning(rescan_lineno, a->name);
1759 if ((a->args = argslen) == 0)
1761 a->argnames = TMALLOC(char *, argslen);
1762 NO_SPACE(a->argnames);
1763 a->argtags = TMALLOC(char *, argslen);
1764 NO_SPACE(a->argtags);
1768 for (i = 0; i < argslen; i++)
1781 if (!(p = parse_id(p + 1, &tmp)))
1790 if (a->argtags[i] != tmp)
1791 arg_type_disagree_warning(rescan_lineno, i + 1, a->name);
1794 a->argtags[i] = tmp;
1797 a->argtags[i] = NULL;
1798 if (!(p = parse_id(p, &a->argnames[i])))
1810 compile_arg(char **theptr, char *yyvaltag)
1813 struct mstring *c = msnew();
1815 Value_t *offsets = NULL, maxoffset;
1820 for (i = nitems - 1; pitem[i]; --i)
1823 if (pitem[i]->class != ARGUMENT)
1828 offsets = TMALLOC(Value_t, maxoffset + 1);
1831 for (j = 0, i++; i < nitems; i++)
1832 if (pitem[i]->class != ARGUMENT)
1833 offsets[++j] = (Value_t) (i - nitems + 1);
1835 rhs = pitem + nitems - 1;
1838 msprintf(c, "yyval.%s = ", yyvaltag);
1840 msprintf(c, "yyval = ");
1847 if (!(p = parse_id(++p, &tag)) || *p++ != '>')
1848 illegal_tag(rescan_lineno, NULL, NULL);
1849 if (isdigit(*p) || *p == '-')
1852 if (!(p = parse_int(p, &val)))
1853 dollar_error(rescan_lineno, NULL, NULL);
1856 else if (val > maxoffset)
1858 dollar_warning(rescan_lineno, val);
1859 i = val - maxoffset;
1861 else if (maxoffset > 0)
1864 if (!tag && !(tag = rhs[i]->tag) && havetags)
1865 untyped_rhs(val, rhs[i]->name);
1867 msprintf(c, "yystack.l_mark[%d]", i);
1869 msprintf(c, ".%s", tag);
1873 else if (isalpha(*p) || *p == '_')
1876 if (!(p = parse_id(p, &arg)))
1877 dollar_error(rescan_lineno, NULL, NULL);
1878 for (i = plhs[nrules]->args - 1; i >= 0; i--)
1879 if (arg == plhs[nrules]->argnames[i])
1882 unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL);
1884 tag = plhs[nrules]->argtags[i];
1885 msprintf(c, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1
1888 msprintf(c, ".%s", tag);
1890 untyped_arg_warning(rescan_lineno, "$", arg);
1893 dollar_error(rescan_lineno, NULL, NULL);
1897 at_error(rescan_lineno, NULL, NULL);
1912 #define ARG_CACHE_SIZE 1024
1913 static struct arg_cache
1915 struct arg_cache *next;
1919 *arg_cache[ARG_CACHE_SIZE];
1922 lookup_arg_cache(char *code)
1924 struct arg_cache *entry;
1926 entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE];
1929 if (!strnscmp(entry->code, code))
1931 entry = entry->next;
1937 insert_arg_cache(char *code, int rule)
1939 struct arg_cache *entry = NEW(struct arg_cache);
1943 i = strnshash(code) % ARG_CACHE_SIZE;
1946 entry->next = arg_cache[i];
1947 arg_cache[i] = entry;
1951 clean_arg_cache(void)
1953 struct arg_cache *e, *t;
1956 for (i = 0; i < ARG_CACHE_SIZE; i++)
1958 for (e = arg_cache[i]; (t = e); e = e->next, FREE(t))
1960 arg_cache[i] = NULL;
1966 advance_to_start(void)
1972 #if defined(YYBTYACC)
1997 syntax_error(lineno, line, s_cptr);
2002 if (!isalpha(c) && c != '_' && c != '.' && c != '_')
2003 syntax_error(lineno, line, cptr);
2007 if (bp->class == TERM)
2008 terminal_start(bp->name);
2016 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2017 #if defined(YYBTYACC)
2021 args = copy_args(&argslen);
2027 syntax_error(lineno, line, cptr);
2028 start_rule(bp, s_lineno);
2029 #if defined(YYBTYACC)
2030 parse_arginfo(bp, args, argslen);
2036 start_rule(bucket *bp, int s_lineno)
2038 if (bp->class == TERM)
2039 terminal_lhs(s_lineno);
2040 bp->class = NONTERM;
2043 if (nrules >= maxrules)
2046 rprec[nrules] = UNDEFINED;
2047 rassoc[nrules] = TOKEN;
2055 if (!last_was_action && plhs[nrules]->tag)
2057 if (pitem[nitems - 1])
2059 for (i = nitems - 1; (i > 0) && pitem[i]; --i)
2061 if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag)
2062 default_action_warning();
2066 default_action_warning();
2070 last_was_action = 0;
2071 if (nitems >= maxitems)
2079 insert_empty_rule(void)
2084 sprintf(cache, "$$%d", ++gensym);
2085 bp = make_bucket(cache);
2086 last_symbol->next = bp;
2088 bp->tag = plhs[nrules]->tag;
2090 #if defined(YYBTYACC)
2094 nitems = (Value_t) (nitems + 2);
2095 if (nitems > maxitems)
2097 bpp = pitem + nitems - 1;
2099 while ((bpp[0] = bpp[-1]) != 0)
2102 if (++nrules >= maxrules)
2104 plhs[nrules] = plhs[nrules - 1];
2105 plhs[nrules - 1] = bp;
2106 rprec[nrules] = rprec[nrules - 1];
2107 rprec[nrules - 1] = 0;
2108 rassoc[nrules] = rassoc[nrules - 1];
2109 rassoc[nrules - 1] = TOKEN;
2112 #if defined(YYBTYACC)
2114 insert_arg_rule(char *arg, char *tag)
2116 int line_number = rescan_lineno;
2117 char *code = compile_arg(&arg, tag);
2118 int rule = lookup_arg_cache(code);
2119 FILE *f = action_file;
2124 insert_arg_cache(code, rule);
2125 fprintf(f, "case %d:\n", rule - 2);
2127 fprintf(f, line_format, line_number, input_file_name);
2128 fprintf(f, "%s;\n", code);
2129 fprintf(f, "break;\n");
2130 insert_empty_rule();
2131 plhs[rule]->tag = tag;
2132 plhs[rule]->class = ARGUMENT;
2136 if (++nitems > maxitems)
2138 pitem[nitems - 1] = plhs[rule];
2150 int s_lineno = lineno;
2151 #if defined(YYBTYACC)
2157 if (c == '\'' || c == '"')
2163 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2164 #if defined(YYBTYACC)
2168 args = copy_args(&argslen);
2176 start_rule(bp, s_lineno);
2177 #if defined(YYBTYACC)
2178 parse_arginfo(bp, args, argslen);
2184 if (last_was_action)
2185 insert_empty_rule();
2186 last_was_action = 0;
2188 #if defined(YYBTYACC)
2191 if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL)
2194 if (plhs[nrules]->args != bp->args)
2195 wrong_number_args_warning("default ", bp->name);
2196 for (i = bp->args - 1; i >= 0; i--)
2197 if (plhs[nrules]->argtags[i] != bp->argtags[i])
2198 wrong_type_for_arg_warning(i + 1, bp->name);
2200 else if (bp->args != argslen)
2201 wrong_number_args_warning("", bp->name);
2202 if (bp->args > 0 && argslen > 0)
2206 for (ap = args, i = 0; i < argslen; i++)
2207 ap = insert_arg_rule(ap, bp->argtags[i]);
2210 #endif /* defined(YYBTYACC) */
2212 if (++nitems > maxitems)
2214 pitem[nitems - 1] = bp;
2223 #if defined(YYBTYACC)
2224 int trialaction = 0;
2228 FILE *f = action_file;
2229 int a_lineno = lineno;
2230 char *a_line = dup_line();
2231 char *a_cptr = a_line + (cptr - line);
2232 Value_t *offsets = NULL, maxoffset;
2235 if (last_was_action)
2236 insert_empty_rule();
2237 last_was_action = 1;
2239 fprintf(f, "case %d:\n", nrules - 2);
2240 #if defined(YYBTYACC)
2243 if (*cptr != L_BRAC)
2244 fprintf(f, " if (!yytrial)\n");
2250 fprintf(f, line_format, lineno, input_file_name);
2254 /* avoid putting curly-braces in first column, to ease editing */
2255 if (*after_blanks(cptr) == L_CURL)
2258 cptr = after_blanks(cptr);
2263 for (i = nitems - 1; pitem[i]; --i)
2266 if (pitem[i]->class != ARGUMENT)
2271 offsets = TMALLOC(Value_t, maxoffset + 1);
2274 for (j = 0, i++; i < nitems; i++)
2276 if (pitem[i]->class != ARGUMENT)
2278 offsets[++j] = (Value_t) (i - nitems + 1);
2282 rhs = pitem + nitems - 1;
2291 int d_lineno = lineno;
2292 char *d_line = dup_line();
2293 char *d_cptr = d_line + (cptr - line);
2300 fprintf(f, "yyval.%s", tag);
2305 else if (isdigit(c))
2309 fprintf(f, "yystack.l_mark[%d].%s", -n, tag);
2310 else if (i > maxoffset)
2312 dollar_warning(d_lineno, i);
2313 fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag);
2316 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2320 else if (c == '-' && isdigit(UCH(cptr[1])))
2323 i = -get_number() - n;
2324 fprintf(f, "yystack.l_mark[%d].%s", i, tag);
2328 #if defined(YYBTYACC)
2329 else if (isalpha(c) || c == '_')
2331 char *arg = scan_id();
2332 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2333 if (arg == plhs[nrules]->argnames[i])
2336 unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr);
2337 fprintf(f, "yystack.l_mark[%d].%s", i - plhs[nrules]->args +
2344 dollar_error(d_lineno, d_line, d_cptr);
2346 else if (cptr[1] == '$')
2350 tag = plhs[nrules]->tag;
2353 fprintf(f, "yyval.%s", tag);
2356 fprintf(f, "yyval");
2358 #if defined(YYBTYACC)
2363 else if (isdigit(UCH(cptr[1])))
2367 if (havetags && offsets)
2369 if (i <= 0 || i > maxoffset)
2371 tag = rhs[offsets[i]]->tag;
2373 untyped_rhs(i, rhs[offsets[i]]->name);
2374 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2379 fprintf(f, "yystack.l_mark[%d]", -n);
2380 else if (i > maxoffset)
2382 dollar_warning(lineno, i);
2383 fprintf(f, "yystack.l_mark[%d]", i - maxoffset);
2386 fprintf(f, "yystack.l_mark[%d]", offsets[i]);
2390 else if (cptr[1] == '-')
2396 fprintf(f, "yystack.l_mark[%d]", -i - n);
2399 #if defined(YYBTYACC)
2400 else if (isalpha(cptr[1]) || cptr[1] == '_')
2405 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2406 if (arg == plhs[nrules]->argnames[i])
2409 unknown_arg_warning(lineno, "$", arg, line, cptr);
2410 tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]);
2411 fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n);
2413 fprintf(f, ".%s", tag);
2415 untyped_arg_warning(lineno, "$", arg);
2420 #if defined(YYBTYACC)
2425 int l_lineno = lineno;
2426 char *l_line = dup_line();
2427 char *l_cptr = l_line + (cptr - line);
2428 syntax_error(l_lineno, l_line, l_cptr);
2432 fprintf(f, "yyloc");
2436 else if (isdigit(UCH(cptr[1])))
2441 fprintf(f, "yystack.p_mark[%d]", -n);
2442 else if (i > maxoffset)
2444 at_warning(lineno, i);
2445 fprintf(f, "yystack.p_mark[%d]", i - maxoffset);
2448 fprintf(f, "yystack.p_mark[%d]", offsets[i]);
2453 if (isalpha(c) || c == '_' || c == '$')
2460 while (isalnum(c) || c == '_' || c == '$');
2464 #if defined(YYBTYACC)
2467 if (trialaction && c == L_BRAC && depth == 0)
2473 if (trialaction && c == R_BRAC && depth == 1)
2478 if (c == L_BRAC && !haveyyval)
2482 if (c == L_CURL && !haveyyval)
2484 fprintf(f, " if (!yytrial)\n");
2486 fprintf(f, line_format, lineno, input_file_name);
2490 fprintf(f, "\nbreak;\n");
2505 unterminated_action(a_lineno, a_line, a_cptr);
2510 fprintf(f, "\nbreak;\n");
2516 #if defined(YYBTYACC)
2535 #if defined(YYBTYACC)
2539 if (c == L_BRAC && !haveyyval)
2544 if (c == L_CURL && !haveyyval)
2546 fprintf(f, " if (!yytrial)\n");
2548 fprintf(f, line_format, lineno, input_file_name);
2553 fprintf(f, "\nbreak;\n");
2562 char *s = copy_string(c);
2570 char *s = copy_comment();
2581 #if defined(YYBTYACC)
2583 copy_destructor(void)
2589 struct mstring *destructor_text = msnew();
2596 msprintf(destructor_text, line_format, lineno, input_file_name);
2598 cptr = after_blanks(cptr);
2599 if (*cptr == L_CURL)
2600 /* avoid putting curly-braces in first column, to ease editing */
2601 mputc(destructor_text, '\t');
2603 syntax_error(lineno, line, cptr);
2606 a_line = dup_line();
2607 a_cptr = a_line + (cptr - line);
2616 int d_lineno = lineno;
2617 char *d_line = dup_line();
2618 char *d_cptr = d_line + (cptr - line);
2625 msprintf(destructor_text, "(*val).%s", tag);
2631 dollar_error(d_lineno, d_line, d_cptr);
2633 else if (cptr[1] == '$')
2635 /* process '$$' later; replacement is context dependent */
2636 msprintf(destructor_text, "$$");
2641 if (c == '@' && cptr[1] == '$')
2645 int l_lineno = lineno;
2646 char *l_line = dup_line();
2647 char *l_cptr = l_line + (cptr - line);
2648 syntax_error(l_lineno, l_line, l_cptr);
2650 msprintf(destructor_text, "(*loc)");
2654 if (isalpha(c) || c == '_' || c == '$')
2658 mputc(destructor_text, c);
2661 while (isalnum(c) || c == '_' || c == '$');
2665 mputc(destructor_text, c);
2672 unterminated_action(a_lineno, a_line, a_cptr);
2681 goto process_symbols;
2686 char *s = copy_string(c);
2687 msprintf(destructor_text, "%s", s);
2694 char *s = copy_comment();
2695 msprintf(destructor_text, "%s", s);
2704 code_text = msdone(destructor_text);
2713 { /* "no semantic type" default destructor */
2715 if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL)
2717 static char untyped_default[] = "<>";
2718 bp = make_bucket("untyped default");
2719 bp->tag = untyped_default;
2720 default_destructor[UNTYPED_DEFAULT] = bp;
2722 if (bp->destructor != NULL)
2723 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2725 /* replace "$$" with "(*val)" in destructor code */
2726 bp->destructor = process_destructor_XX(code_text, NULL);
2728 else if (cptr[1] == '*' && cptr[2] == '>')
2729 { /* "no per-symbol or per-type" default destructor */
2731 if ((bp = default_destructor[TYPED_DEFAULT]) == NULL)
2733 static char typed_default[] = "<*>";
2734 bp = make_bucket("typed default");
2735 bp->tag = typed_default;
2736 default_destructor[TYPED_DEFAULT] = bp;
2738 if (bp->destructor != NULL)
2739 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2742 /* postpone re-processing destructor $$s until end of grammar spec */
2743 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2744 NO_SPACE(bp->destructor);
2745 strcpy(bp->destructor, code_text);
2749 { /* "semantic type" default destructor */
2751 bp = lookup_type_destructor(tag);
2752 if (bp->destructor != NULL)
2753 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2755 /* replace "$$" with "(*val).tag" in destructor code */
2756 bp->destructor = process_destructor_XX(code_text, tag);
2759 else if (isalpha(c) || c == '_' || c == '.' || c == '$')
2760 { /* "symbol" destructor */
2762 if (bp->destructor != NULL)
2763 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2766 /* postpone re-processing destructor $$s until end of grammar spec */
2767 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2768 NO_SPACE(bp->destructor);
2769 strcpy(bp->destructor, code_text);
2780 process_destructor_XX(char *code, char *tag)
2785 struct mstring *new_code = msnew();
2786 char *codeptr = code;
2789 loop: /* step thru code */
2791 if (c == '$' && codeptr[1] == '$')
2795 msprintf(new_code, "(*val)");
2797 msprintf(new_code, "(*val).%s", tag);
2800 if (isalpha(c) || c == '_' || c == '$')
2807 while (isalnum(c) || c == '_' || c == '$');
2821 return msdone(new_code);
2849 if (c == '*' && *codeptr == '/')
2851 mputc(new_code, '/');
2863 #endif /* defined(YYBTYACC) */
2872 if (c == '%' || c == '\\')
2880 else if ((c == 'p' || c == 'P') &&
2881 ((c = cptr[2]) == 'r' || c == 'R') &&
2882 ((c = cptr[3]) == 'e' || c == 'E') &&
2883 ((c = cptr[4]) == 'c' || c == 'C') &&
2884 ((c = cptr[5], !IS_IDENT(c))))
2887 syntax_error(lineno, line, cptr);
2890 if (isalpha(c) || c == '_' || c == '.' || c == '$')
2892 else if (c == '\'' || c == '"')
2896 syntax_error(lineno, line, cptr);
2899 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
2902 rprec[nrules] = bp->prec;
2903 rassoc[nrules] = bp->assoc;
2912 initialize_grammar();
2927 #if defined(YYBTYACC)
2928 else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC))
2930 else if (c == L_CURL || c == '=')
2936 start_rule(plhs[nrules - 1], 0);
2945 syntax_error(lineno, line, cptr);
2948 #if defined(YYBTYACC)
2950 start_requires_args(goal->name);
2962 for (i = 0; i < ntags; ++i)
2964 assert(tag_table[i]);
2976 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
2977 for (bp = first_symbol; bp; bp = bp->next)
2978 name_pool_size += strlen(bp->name) + 1;
2980 name_pool = TMALLOC(char, name_pool_size);
2981 NO_SPACE(name_pool);
2983 strcpy(name_pool, "$accept");
2984 strcpy(name_pool + 8, "$end");
2986 for (bp = first_symbol; bp; bp = bp->next)
2990 while ((*t++ = *s++) != 0)
3002 if (goal->class == UNKNOWN)
3003 undefined_goal(goal->name);
3005 for (bp = first_symbol; bp; bp = bp->next)
3007 if (bp->class == UNKNOWN)
3009 undefined_symbol_warning(bp->name);
3016 protect_string(char *src, char **des)
3029 if ('\\' == *s || '"' == *s)
3035 *des = d = TMALLOC(char, len);
3041 if ('\\' == *s || '"' == *s)
3055 #if defined(YYBTYACC)
3056 Value_t max_tok_pval;
3061 for (bp = first_symbol; bp; bp = bp->next)
3064 if (bp->class == TERM)
3067 start_symbol = (Value_t) ntokens;
3068 nvars = (Value_t) (nsyms - ntokens);
3070 symbol_name = TMALLOC(char *, nsyms);
3071 NO_SPACE(symbol_name);
3073 symbol_value = TMALLOC(Value_t, nsyms);
3074 NO_SPACE(symbol_value);
3076 symbol_prec = TMALLOC(Value_t, nsyms);
3077 NO_SPACE(symbol_prec);
3079 symbol_assoc = TMALLOC(char, nsyms);
3080 NO_SPACE(symbol_assoc);
3082 #if defined(YYBTYACC)
3083 symbol_pval = TMALLOC(Value_t, nsyms);
3084 NO_SPACE(symbol_pval);
3088 symbol_destructor = CALLOC(sizeof(char *), nsyms);
3089 NO_SPACE(symbol_destructor);
3091 symbol_type_tag = CALLOC(sizeof(char *), nsyms);
3092 NO_SPACE(symbol_type_tag);
3096 v = TMALLOC(bucket *, nsyms);
3100 v[start_symbol] = 0;
3103 j = (Value_t) (start_symbol + 1);
3104 for (bp = first_symbol; bp; bp = bp->next)
3106 if (bp->class == TERM)
3111 assert(i == ntokens && j == nsyms);
3113 for (i = 1; i < ntokens; ++i)
3116 goal->index = (Index_t) (start_symbol + 1);
3117 k = (Value_t) (start_symbol + 2);
3127 for (i = (Value_t) (start_symbol + 1); i < nsyms; ++i)
3137 for (i = 1; i < ntokens; ++i)
3142 for (j = k++; j > 0 && symbol_value[j - 1] > n; --j)
3143 symbol_value[j] = symbol_value[j - 1];
3144 symbol_value[j] = n;
3150 if (v[1]->value == UNDEFINED)
3155 for (i = 2; i < ntokens; ++i)
3157 if (v[i]->value == UNDEFINED)
3159 while (j < k && n == symbol_value[j])
3161 while (++j < k && n == symbol_value[j])
3170 symbol_name[0] = name_pool + 8;
3171 symbol_value[0] = 0;
3173 symbol_assoc[0] = TOKEN;
3174 #if defined(YYBTYACC)
3178 for (i = 1; i < ntokens; ++i)
3180 symbol_name[i] = v[i]->name;
3181 symbol_value[i] = v[i]->value;
3182 symbol_prec[i] = v[i]->prec;
3183 symbol_assoc[i] = v[i]->assoc;
3184 #if defined(YYBTYACC)
3185 symbol_pval[i] = v[i]->value;
3186 if (symbol_pval[i] > max_tok_pval)
3187 max_tok_pval = symbol_pval[i];
3190 symbol_destructor[i] = v[i]->destructor;
3191 symbol_type_tag[i] = v[i]->tag;
3195 symbol_name[start_symbol] = name_pool;
3196 symbol_value[start_symbol] = -1;
3197 symbol_prec[start_symbol] = 0;
3198 symbol_assoc[start_symbol] = TOKEN;
3199 #if defined(YYBTYACC)
3200 symbol_pval[start_symbol] = (Value_t) (max_tok_pval + 1);
3202 for (++i; i < nsyms; ++i)
3205 symbol_name[k] = v[i]->name;
3206 symbol_value[k] = v[i]->value;
3207 symbol_prec[k] = v[i]->prec;
3208 symbol_assoc[k] = v[i]->assoc;
3209 #if defined(YYBTYACC)
3210 symbol_pval[k] = (Value_t) ((max_tok_pval + 1) + v[i]->value + 1);
3213 symbol_destructor[k] = v[i]->destructor;
3214 symbol_type_tag[k] = v[i]->tag;
3221 symbol_pname = TMALLOC(char *, nsyms);
3222 NO_SPACE(symbol_pname);
3224 for (i = 0; i < nsyms; ++i)
3225 protect_string(symbol_name[i], &(symbol_pname[i]));
3239 ritem = TMALLOC(Value_t, nitems);
3242 rlhs = TMALLOC(Value_t, nrules);
3245 rrhs = TMALLOC(Value_t, nrules + 1);
3248 rprec = TREALLOC(Value_t, rprec, nrules);
3251 rassoc = TREALLOC(Assoc_t, rassoc, nrules);
3255 ritem[1] = goal->index;
3260 rlhs[2] = start_symbol;
3266 for (i = 3; i < nrules; ++i)
3268 #if defined(YYBTYACC)
3269 if (plhs[i]->args > 0)
3271 if (plhs[i]->argnames)
3273 FREE(plhs[i]->argnames);
3274 plhs[i]->argnames = NULL;
3276 if (plhs[i]->argtags)
3278 FREE(plhs[i]->argtags);
3279 plhs[i]->argtags = NULL;
3282 #endif /* defined(YYBTYACC) */
3283 rlhs[i] = plhs[i]->index;
3289 ritem[j] = pitem[j]->index;
3290 if (pitem[j]->class == TERM)
3292 prec2 = pitem[j]->prec;
3293 assoc = pitem[j]->assoc;
3297 ritem[j] = (Value_t) - i;
3299 if (rprec[i] == UNDEFINED)
3309 #if defined(YYBTYACC)
3318 size_t j, spacing = 0;
3319 FILE *f = verbose_file;
3325 for (i = 2; i < nrules; ++i)
3327 if (rlhs[i] != rlhs[i - 1])
3331 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
3332 spacing = strlen(symbol_name[rlhs[i]]) + 1;
3336 fprintf(f, "%4d ", i - 2);
3343 while (ritem[k] >= 0)
3345 fprintf(f, " %s", symbol_name[ritem[k]]);
3353 #if defined(YYBTYACC)
3355 finalize_destructors(void)
3361 for (i = 2; i < nsyms; ++i)
3363 tag = symbol_type_tag[i];
3364 if (symbol_destructor[i] == NULL)
3367 { /* use <> destructor, if there is one */
3368 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3370 symbol_destructor[i] = TMALLOC(char,
3371 strlen(bp->destructor) + 1);
3372 NO_SPACE(symbol_destructor[i]);
3373 strcpy(symbol_destructor[i], bp->destructor);
3377 { /* use type destructor for this tag, if there is one */
3378 bp = lookup_type_destructor(tag);
3379 if (bp->destructor != NULL)
3381 symbol_destructor[i] = TMALLOC(char,
3382 strlen(bp->destructor) + 1);
3383 NO_SPACE(symbol_destructor[i]);
3384 strcpy(symbol_destructor[i], bp->destructor);
3387 { /* use <*> destructor, if there is one */
3388 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3389 /* replace "$$" with "(*val).tag" in destructor code */
3390 symbol_destructor[i]
3391 = process_destructor_XX(bp->destructor, tag);
3396 { /* replace "$$" with "(*val)[.tag]" in destructor code */
3397 symbol_destructor[i]
3398 = process_destructor_XX(symbol_destructor[i], tag);
3401 /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */
3402 DO_FREE(symbol_type_tag); /* no longer needed */
3403 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3406 /* 'bp->tag' is a static value, don't free */
3407 FREE(bp->destructor);
3410 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3413 /* 'bp->tag' is a static value, don't free */
3414 FREE(bp->destructor);
3417 if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL)
3424 /* 'bp->tag' freed by 'free_tags()' */
3425 FREE(bp->destructor);
3430 #endif /* defined(YYBTYACC) */
3435 write_section(code_file, banner);
3436 create_symbol_table();
3437 read_declarations();
3439 free_symbol_table();
3446 #if defined(YYBTYACC)
3448 finalize_destructors();
3455 free_declarations(param * list)
3459 param *next = list->next;
3472 lex_param = free_declarations(lex_param);
3473 parse_param = free_declarations(parse_param);
3483 DO_FREE(symbol_name);
3484 DO_FREE(symbol_prec);
3485 DO_FREE(symbol_assoc);
3486 DO_FREE(symbol_value);
3487 #if defined(YYBTYACC)
3488 DO_FREE(symbol_pval);
3489 DO_FREE(symbol_destructor);
3490 DO_FREE(symbol_type_tag);