1 /* $Id: reader.c,v 1.60 2016/03/25 00:51:07 tom Exp $ */
5 /* The line size must be a positive integer. One hundred was chosen */
6 /* because few lines in Yacc input grammars exceed 100 characters. */
7 /* Note that if a line exceeds LINESIZE characters, the line buffer */
8 /* will be expanded to accomodate it. */
19 /* the maximum number of arguments (inherited attributes) to a non-terminal */
20 /* this is a hard limit, but seems more than adequate */
23 static void start_rule(bucket *bp, int s_lineno);
25 static void copy_destructor(void);
26 static char *process_destructor_XX(char *code, char *tag);
29 #define CACHE_SIZE 256
31 static int cinc, cache_size;
34 static int tagmax, havetags;
35 static char **tag_table;
45 static char last_was_action;
48 static bucket **pitem;
53 static size_t name_pool_size;
54 static char *name_pool;
56 char line_format[] = "#line %d \"%s\"\n";
62 int destructor = 0; /* =1 if at least one %destructor */
64 static bucket *default_destructor[3] =
67 #define UNTYPED_DEFAULT 0
68 #define TYPED_DEFAULT 1
69 #define TYPE_SPECIFIED 2
72 lookup_type_destructor(char *tag)
74 const char fmt[] = "%.*s destructor";
75 char name[1024] = "\0";
76 bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED];
78 while ((bp = *bpp) != NULL)
85 sprintf(name, fmt, (int)(sizeof(name) - sizeof(fmt)), tag);
86 *bpp = bp = make_bucket(name);
91 #endif /* defined(YYBTYACC) */
97 if (cinc >= cache_size)
99 cache_size += CACHE_SIZE;
100 cache = TREALLOC(char, cache, cache_size);
103 cache[cinc] = (char)c;
110 FILE *f = input_file;
114 if (saw_eof || (c = getc(f)) == EOF)
126 if (line == 0 || linesize != (LINESIZE + 1))
130 linesize = LINESIZE + 1;
131 line = TMALLOC(char, linesize);
142 if ((i + 3) >= linesize)
144 linesize += LINESIZE;
145 line = TREALLOC(char, line, linesize);
171 p = TMALLOC(char, s - line + 1);
176 while ((*t++ = *s++) != '\n')
186 int st_lineno = lineno;
187 char *st_line = dup_line();
188 char *st_cptr = st_line + (cptr - line);
193 if (*s == '*' && s[1] == '/')
203 unterminated_comment(st_lineno, st_line, st_cptr);
236 else if (s[1] == '/')
261 switch (ch = next_inline())
288 static struct keyword
294 { "binary", NONASSOC },
295 #if defined(YYBTYACC)
296 { "destructor", DESTRUCTOR },
298 { "expect", EXPECT },
299 { "expect-rr", EXPECT_RR },
302 { "lex-param", LEX_PARAM },
303 #if defined(YYBTYACC)
304 { "locations", LOCATIONS },
306 { "nonassoc", NONASSOC },
307 { "parse-param", PARSE_PARAM },
308 { "pure-parser", PURE_PARSER },
313 { "token-table", TOKEN_TABLE },
316 { "yacc", POSIX_YACC },
321 compare_keys(const void *a, const void *b)
323 const struct keyword *p = (const struct keyword *)a;
324 const struct keyword *q = (const struct keyword *)b;
325 return strcmp(p->name, q->name);
356 /* treat keywords spelled with '_' as if it were '-' */
367 if ((key = bsearch(cache, keywords,
368 sizeof(keywords) / sizeof(*key),
369 sizeof(*key), compare_keys)))
377 if (c == '%' || c == '\\')
388 syntax_error(lineno, line, t_cptr);
396 FILE *f = output_file;
402 syntax_error(lineno, line, cptr);
404 fprintf(f, "#ident \"");
424 copy_string(int quote)
426 struct mstring *temp = msnew();
428 int s_lineno = lineno;
429 char *s_line = dup_line();
430 char *s_cptr = s_line + (cptr - line - 1);
442 unterminated_string(s_lineno, s_line, s_cptr);
451 unterminated_string(s_lineno, s_line, s_cptr);
460 struct mstring *temp = msnew();
467 while ((c = *++cptr) != '\n')
470 if (c == '*' && cptr[1] == '/')
478 int c_lineno = lineno;
479 char *c_line = dup_line();
480 char *c_cptr = c_line + (cptr - line - 1);
488 if (c == '*' && *cptr == '/')
499 unterminated_comment(c_lineno, c_line, c_cptr);
511 int need_newline = 0;
512 int t_lineno = lineno;
513 char *t_line = dup_line();
514 char *t_cptr = t_line + (cptr - line - 2);
520 unterminated_text(t_lineno, t_line, t_cptr);
523 fprintf(f, line_format, lineno, input_file_name);
535 unterminated_text(t_lineno, t_line, t_cptr);
541 char *s = copy_string(c);
551 char *s = copy_comment();
578 puts_both(const char *s)
582 fputs(s, union_file);
598 int u_lineno = lineno;
599 char *u_line = dup_line();
600 char *u_cptr = u_line + (cptr - line - 6);
603 over_unionized(cptr - 6);
607 fprintf(text_file, line_format, lineno, input_file_name);
609 puts_both("#ifdef YYSTYPE\n");
610 puts_both("#undef YYSTYPE_IS_DECLARED\n");
611 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
612 puts_both("#endif\n");
613 puts_both("#ifndef YYSTYPE_IS_DECLARED\n");
614 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
615 puts_both("typedef union");
626 unterminated_union(u_lineno, u_line, u_cptr);
636 puts_both(" YYSTYPE;\n");
637 puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n");
646 char *s = copy_string(c);
654 char *s = copy_comment();
666 after_blanks(char *s)
668 while (*s != '\0' && isspace(UCH(*s)))
674 * Trim leading/trailing blanks, and collapse multiple embedded blanks to a
675 * single space. Return index to last character in the buffer.
678 trim_blanks(char *buffer)
683 char *s = after_blanks(d);
685 while ((*d++ = *s++) != '\0')
691 while ((--d != buffer) && isspace(UCH(*d)))
694 for (s = d = buffer; (*d++ = *s++) != '\0';)
696 if (isspace(UCH(*s)))
699 while (isspace(UCH(*s)))
708 return (int)strlen(buffer) - 1;
712 * Scan forward in the current line-buffer looking for a right-curly bracket.
714 * Parameters begin with a left-curly bracket, and continue until there are no
715 * more interesting characters after the last right-curly bracket on the
716 * current line. Bison documents parameters as separated like this:
717 * {type param1} {type2 param2}
718 * but also accepts commas (although some versions of bison mishandle this)
719 * {type param1, type2 param2}
729 switch (next_inline())
748 save_param(int k, char *buffer, int name, int type2)
752 p = TMALLOC(param, 1);
755 p->type2 = strdup(buffer + type2);
757 buffer[type2] = '\0';
758 (void)trim_blanks(p->type2);
760 p->name = strdup(buffer + name);
763 (void)trim_blanks(p->name);
765 p->type = strdup(buffer);
767 (void)trim_blanks(p->type);
791 * Keep a linked list of parameters. This may be multi-line, if the trailing
792 * right-curly bracket is absent.
803 int st_lineno = lineno;
837 if ((curly == 1) && (cptr == line))
847 if (curly == 0 && !isspace(UCH(c)))
855 buf_size = (size_t) linesize;
856 buf = TMALLOC(char, buf_size);
864 buf_size += (size_t) linesize;
865 buf = TREALLOC(char, buf, buf_size);
870 if ((state == 2) && (c == L_CURL))
874 else if ((state == 2) && isspace(UCH(c)))
878 else if ((c != L_CURL) && (c != R_CURL))
885 while (curly < 2 || more_curly());
898 (void)trim_blanks(buf);
903 char *parms = (comma + 1);
904 comma = strchr(parms, ',');
908 (void)trim_blanks(parms);
909 i = (int)strlen(parms) - 1;
918 while (i >= 0 && level > 0 && parms[i] != '[')
922 else if (parms[i] == '[')
935 while (i > 0 && (isalnum(UCH(parms[i])) || UCH(parms[i]) == '_'))
938 if (!isspace(UCH(parms[i])) && parms[i] != '*')
943 save_param(k, parms, name, type2);
951 syntax_error(lineno, line, cptr);
957 if (c >= '0' && c <= '9')
959 if (c >= 'A' && c <= 'F')
960 return (c - 'A' + 10);
961 if (c >= 'a' && c <= 'f')
962 return (c - 'a' + 10);
974 int s_lineno = lineno;
975 char *s_line = dup_line();
976 char *s_cptr = s_line + (cptr - line);
986 unterminated_string(s_lineno, s_line, s_cptr);
989 char *c_cptr = cptr - 1;
997 unterminated_string(s_lineno, s_line, s_cptr);
1012 n = (n << 3) + (c - '0');
1016 n = (n << 3) + (c - '0');
1021 illegal_character(c_cptr);
1028 if (n < 0 || n >= 16)
1029 illegal_character(c_cptr);
1034 if (i < 0 || i >= 16)
1039 illegal_character(c_cptr);
1072 s = TMALLOC(char, n);
1075 for (i = 0; i < n; ++i)
1084 for (i = 0; i < n; ++i)
1087 if (c == '\\' || c == cache[0])
1092 else if (isprint(c))
1121 cachec(((c >> 6) & 7) + '0');
1122 cachec(((c >> 3) & 7) + '0');
1123 cachec((c & 7) + '0');
1137 if (n == 1 && bp->value == UNDEFINED)
1138 bp->value = UCH(*s);
1145 is_reserved(char *name)
1149 if (strcmp(name, ".") == 0 ||
1150 strcmp(name, "$accept") == 0 ||
1151 strcmp(name, "$end") == 0)
1154 if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2])))
1157 while (isdigit(UCH(*s)))
1172 for (c = *cptr; IS_IDENT(c); c = *++cptr)
1176 if (is_reserved(cache))
1177 used_reserved(cache);
1179 return (lookup(cache));
1189 for (c = *cptr; isdigit(c); c = *++cptr)
1190 n = (Value_t) (10 * n + (c - '0'));
1196 cache_tag(char *tag, size_t len)
1201 for (i = 0; i < ntags; ++i)
1203 if (strncmp(tag, tag_table[i], len) == 0 &&
1204 tag_table[i][len] == NUL)
1205 return (tag_table[i]);
1208 if (ntags >= tagmax)
1213 ? TREALLOC(char *, tag_table, tagmax)
1214 : TMALLOC(char *, tagmax));
1215 NO_SPACE(tag_table);
1218 s = TMALLOC(char, len + 1);
1221 strncpy(s, tag, len);
1223 tag_table[ntags++] = s;
1231 int t_lineno = lineno;
1232 char *t_line = dup_line();
1233 char *t_cptr = t_line + (cptr - line);
1239 if (!isalpha(c) && c != '_' && c != '$')
1240 illegal_tag(t_lineno, t_line, t_cptr);
1248 while (IS_IDENT(c));
1255 illegal_tag(t_lineno, t_line, t_cptr);
1260 return cache_tag(cache, (size_t) cinc);
1263 #if defined(YYBTYACC)
1269 while (isalnum(*cptr) || *cptr == '_' || *cptr == '$')
1271 return cache_tag(b, (size_t) (cptr - b));
1276 declare_tokens(int assoc)
1299 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1301 else if (c == '\'' || c == '"')
1307 tokenized_start(bp->name);
1312 if (bp->tag && tag != bp->tag)
1313 retyped_warning(bp->name);
1319 if (bp->prec && prec != bp->prec)
1320 reprec_warning(bp->name);
1321 bp->assoc = (Assoc_t) assoc;
1331 value = get_number();
1332 if (bp->value != UNDEFINED && value != bp->value)
1333 revalued_warning(bp->name);
1343 * %expect requires special handling
1344 * as it really isn't part of the yacc
1345 * grammar only a flag for yacc proper.
1348 declare_expect(int assoc)
1352 if (assoc != EXPECT && assoc != EXPECT_RR)
1356 * Stay away from nextc - doesn't
1357 * detect EOL and will read to EOF.
1367 if (assoc == EXPECT)
1368 SRexpect = get_number();
1370 RRexpect = get_number();
1374 * Looking for number before EOL.
1375 * Spaces, tabs, and numbers are ok,
1376 * words, punc., etc. are syntax errors.
1378 else if (c == '\n' || isalpha(c) || !isspace(c))
1380 syntax_error(lineno, line, cptr);
1391 #if defined(YYBTYACC)
1393 declare_argtypes(bucket *bp)
1395 char *tags[MAXARGS];
1399 retyped_warning(bp->name);
1400 cptr++; /* skip open paren */
1407 syntax_error(lineno, line, cptr);
1408 tags[args++] = get_tag();
1415 cptr++; /* skip close paren */
1417 bp->argnames = TMALLOC(char *, args);
1418 NO_SPACE(bp->argnames);
1419 bp->argtags = CALLOC(sizeof(char *), args + 1);
1420 NO_SPACE(bp->argtags);
1423 bp->argtags[args] = tags[args];
1424 bp->argnames[args] = NULL;
1447 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1450 #if defined(YYBTYACC)
1451 if (nextc() == L_PAREN)
1452 declare_argtypes(bp);
1457 else if (c == '\'' || c == '"')
1460 #if defined(YYBTYACC)
1469 if (bp->tag && tag != bp->tag)
1470 retyped_warning(bp->name);
1485 if (!isalpha(c) && c != '_' && c != '.' && c != '$')
1486 syntax_error(lineno, line, cptr);
1488 if (bp->class == TERM)
1489 terminal_start(bp->name);
1490 if (goal && goal != bp)
1491 restarted_warning();
1496 read_declarations(void)
1500 cache_size = CACHE_SIZE;
1501 cache = TMALLOC(char, cache_size);
1510 syntax_error(lineno, line, cptr);
1511 switch (k = keyword())
1561 #if defined(YYBTYACC)
1573 /* noop for bison compatibility. byacc is already designed to be posix
1574 * yacc compatible. */
1581 initialize_grammar(void)
1586 pitem = TMALLOC(bucket *, maxitems);
1597 plhs = TMALLOC(bucket *, maxrules);
1604 rprec = TMALLOC(Value_t, maxrules);
1611 rassoc = TMALLOC(Assoc_t, maxrules);
1623 pitem = TREALLOC(bucket *, pitem, maxitems);
1632 plhs = TREALLOC(bucket *, plhs, maxrules);
1635 rprec = TREALLOC(Value_t, rprec, maxrules);
1638 rassoc = TREALLOC(Assoc_t, rassoc, maxrules);
1642 /* set immediately prior to where copy_args() could be called, and incremented by
1643 the various routines that will rescan the argument list as appropriate */
1644 static int rescan_lineno;
1645 #if defined(YYBTYACC)
1648 copy_args(int *alen)
1650 struct mstring *s = msnew();
1651 int depth = 0, len = 1;
1653 int a_lineno = lineno;
1654 char *a_line = dup_line();
1655 char *a_cptr = a_line + (cptr - line - 1);
1657 while ((c = *cptr++) != R_PAREN || depth || quote)
1659 if (c == ',' && !quote && !depth)
1672 unterminated_string(a_lineno, a_line, a_cptr);
1674 unterminated_arglist(a_lineno, a_line, a_cptr);
1691 else if (c == R_PAREN)
1693 else if (c == '\"' || c == '\'')
1704 parse_id(char *p, char **save)
1711 if (!isalpha(*p) && *p != '_')
1714 while (isalnum(*p) || *p == '_' || *p == '$')
1718 *save = cache_tag(b, (size_t) (p - b));
1724 parse_int(char *p, int *save)
1726 int neg = 0, val = 0;
1739 val = val * 10 + *p++ - '0';
1748 parse_arginfo(bucket *a, char *args, int argslen)
1750 char *p = args, *tmp;
1755 if (a->args != argslen)
1756 arg_number_disagree_warning(rescan_lineno, a->name);
1761 if ((a->args = argslen) == 0)
1763 a->argnames = TMALLOC(char *, argslen);
1764 NO_SPACE(a->argnames);
1765 a->argtags = TMALLOC(char *, argslen);
1766 NO_SPACE(a->argtags);
1770 for (i = 0; i < argslen; i++)
1783 if (!(p = parse_id(p + 1, &tmp)))
1792 if (a->argtags[i] != tmp)
1793 arg_type_disagree_warning(rescan_lineno, i + 1, a->name);
1796 a->argtags[i] = tmp;
1799 a->argtags[i] = NULL;
1800 if (!(p = parse_id(p, &a->argnames[i])))
1812 compile_arg(char **theptr, char *yyvaltag)
1815 struct mstring *c = msnew();
1817 Value_t *offsets = NULL, maxoffset;
1822 for (i = nitems - 1; pitem[i]; --i)
1825 if (pitem[i]->class != ARGUMENT)
1830 offsets = TMALLOC(Value_t, maxoffset + 1);
1833 for (j = 0, i++; i < nitems; i++)
1834 if (pitem[i]->class != ARGUMENT)
1835 offsets[++j] = (Value_t) (i - nitems + 1);
1837 rhs = pitem + nitems - 1;
1840 msprintf(c, "yyval.%s = ", yyvaltag);
1842 msprintf(c, "yyval = ");
1849 if (!(p = parse_id(++p, &tag)) || *p++ != '>')
1850 illegal_tag(rescan_lineno, NULL, NULL);
1851 if (isdigit(*p) || *p == '-')
1854 if (!(p = parse_int(p, &val)))
1855 dollar_error(rescan_lineno, NULL, NULL);
1858 else if (val > maxoffset)
1860 dollar_warning(rescan_lineno, val);
1861 i = val - maxoffset;
1863 else if (maxoffset > 0)
1866 if (!tag && !(tag = rhs[i]->tag) && havetags)
1867 untyped_rhs(val, rhs[i]->name);
1869 msprintf(c, "yystack.l_mark[%d]", i);
1871 msprintf(c, ".%s", tag);
1875 else if (isalpha(*p) || *p == '_')
1878 if (!(p = parse_id(p, &arg)))
1879 dollar_error(rescan_lineno, NULL, NULL);
1880 for (i = plhs[nrules]->args - 1; i >= 0; i--)
1881 if (arg == plhs[nrules]->argnames[i])
1884 unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL);
1886 tag = plhs[nrules]->argtags[i];
1887 msprintf(c, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1
1890 msprintf(c, ".%s", tag);
1892 untyped_arg_warning(rescan_lineno, "$", arg);
1895 dollar_error(rescan_lineno, NULL, NULL);
1899 at_error(rescan_lineno, NULL, NULL);
1914 #define ARG_CACHE_SIZE 1024
1915 static struct arg_cache
1917 struct arg_cache *next;
1921 *arg_cache[ARG_CACHE_SIZE];
1924 lookup_arg_cache(char *code)
1926 struct arg_cache *entry;
1928 entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE];
1931 if (!strnscmp(entry->code, code))
1933 entry = entry->next;
1939 insert_arg_cache(char *code, int rule)
1941 struct arg_cache *entry = NEW(struct arg_cache);
1945 i = strnshash(code) % ARG_CACHE_SIZE;
1948 entry->next = arg_cache[i];
1949 arg_cache[i] = entry;
1953 clean_arg_cache(void)
1955 struct arg_cache *e, *t;
1958 for (i = 0; i < ARG_CACHE_SIZE; i++)
1960 for (e = arg_cache[i]; (t = e); e = e->next, FREE(t))
1962 arg_cache[i] = NULL;
1968 advance_to_start(void)
1974 #if defined(YYBTYACC)
1999 syntax_error(lineno, line, s_cptr);
2004 if (!isalpha(c) && c != '_' && c != '.' && c != '_')
2005 syntax_error(lineno, line, cptr);
2009 if (bp->class == TERM)
2010 terminal_start(bp->name);
2018 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2019 #if defined(YYBTYACC)
2023 args = copy_args(&argslen);
2029 syntax_error(lineno, line, cptr);
2030 start_rule(bp, s_lineno);
2031 #if defined(YYBTYACC)
2032 parse_arginfo(bp, args, argslen);
2038 start_rule(bucket *bp, int s_lineno)
2040 if (bp->class == TERM)
2041 terminal_lhs(s_lineno);
2042 bp->class = NONTERM;
2045 if (nrules >= maxrules)
2048 rprec[nrules] = UNDEFINED;
2049 rassoc[nrules] = TOKEN;
2057 if (!last_was_action && plhs[nrules]->tag)
2059 if (pitem[nitems - 1])
2061 for (i = nitems - 1; (i > 0) && pitem[i]; --i)
2063 if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag)
2064 default_action_warning();
2068 default_action_warning();
2072 last_was_action = 0;
2073 if (nitems >= maxitems)
2081 insert_empty_rule(void)
2086 assert(cache_size >= CACHE_SIZE);
2087 sprintf(cache, "$$%d", ++gensym);
2088 bp = make_bucket(cache);
2089 last_symbol->next = bp;
2091 bp->tag = plhs[nrules]->tag;
2093 #if defined(YYBTYACC)
2097 nitems = (Value_t) (nitems + 2);
2098 if (nitems > maxitems)
2100 bpp = pitem + nitems - 1;
2102 while ((bpp[0] = bpp[-1]) != 0)
2105 if (++nrules >= maxrules)
2107 plhs[nrules] = plhs[nrules - 1];
2108 plhs[nrules - 1] = bp;
2109 rprec[nrules] = rprec[nrules - 1];
2110 rprec[nrules - 1] = 0;
2111 rassoc[nrules] = rassoc[nrules - 1];
2112 rassoc[nrules - 1] = TOKEN;
2115 #if defined(YYBTYACC)
2117 insert_arg_rule(char *arg, char *tag)
2119 int line_number = rescan_lineno;
2120 char *code = compile_arg(&arg, tag);
2121 int rule = lookup_arg_cache(code);
2122 FILE *f = action_file;
2127 insert_arg_cache(code, rule);
2128 fprintf(f, "case %d:\n", rule - 2);
2130 fprintf(f, line_format, line_number, input_file_name);
2131 fprintf(f, "%s;\n", code);
2132 fprintf(f, "break;\n");
2133 insert_empty_rule();
2134 plhs[rule]->tag = tag;
2135 plhs[rule]->class = ARGUMENT;
2139 if (++nitems > maxitems)
2141 pitem[nitems - 1] = plhs[rule];
2153 int s_lineno = lineno;
2154 #if defined(YYBTYACC)
2160 if (c == '\'' || c == '"')
2166 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2167 #if defined(YYBTYACC)
2171 args = copy_args(&argslen);
2179 start_rule(bp, s_lineno);
2180 #if defined(YYBTYACC)
2181 parse_arginfo(bp, args, argslen);
2187 if (last_was_action)
2188 insert_empty_rule();
2189 last_was_action = 0;
2191 #if defined(YYBTYACC)
2194 if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL)
2197 if (plhs[nrules]->args != bp->args)
2198 wrong_number_args_warning("default ", bp->name);
2199 for (i = bp->args - 1; i >= 0; i--)
2200 if (plhs[nrules]->argtags[i] != bp->argtags[i])
2201 wrong_type_for_arg_warning(i + 1, bp->name);
2203 else if (bp->args != argslen)
2204 wrong_number_args_warning("", bp->name);
2205 if (bp->args > 0 && argslen > 0)
2209 for (ap = args, i = 0; i < argslen; i++)
2210 ap = insert_arg_rule(ap, bp->argtags[i]);
2213 #endif /* defined(YYBTYACC) */
2215 if (++nitems > maxitems)
2217 pitem[nitems - 1] = bp;
2226 #if defined(YYBTYACC)
2227 int trialaction = 0;
2231 FILE *f = action_file;
2232 int a_lineno = lineno;
2233 char *a_line = dup_line();
2234 char *a_cptr = a_line + (cptr - line);
2235 Value_t *offsets = NULL, maxoffset;
2238 if (last_was_action)
2239 insert_empty_rule();
2240 last_was_action = 1;
2242 fprintf(f, "case %d:\n", nrules - 2);
2243 #if defined(YYBTYACC)
2246 if (*cptr != L_BRAC)
2247 fprintf(f, " if (!yytrial)\n");
2253 fprintf(f, line_format, lineno, input_file_name);
2257 /* avoid putting curly-braces in first column, to ease editing */
2258 if (*after_blanks(cptr) == L_CURL)
2261 cptr = after_blanks(cptr);
2266 for (i = nitems - 1; pitem[i]; --i)
2269 if (pitem[i]->class != ARGUMENT)
2274 offsets = TMALLOC(Value_t, maxoffset + 1);
2277 for (j = 0, i++; i < nitems; i++)
2279 if (pitem[i]->class != ARGUMENT)
2281 offsets[++j] = (Value_t) (i - nitems + 1);
2285 rhs = pitem + nitems - 1;
2294 int d_lineno = lineno;
2295 char *d_line = dup_line();
2296 char *d_cptr = d_line + (cptr - line);
2303 fprintf(f, "yyval.%s", tag);
2308 else if (isdigit(c))
2312 fprintf(f, "yystack.l_mark[%d].%s", -n, tag);
2313 else if (i > maxoffset)
2315 dollar_warning(d_lineno, i);
2316 fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag);
2319 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2323 else if (c == '-' && isdigit(UCH(cptr[1])))
2326 i = -get_number() - n;
2327 fprintf(f, "yystack.l_mark[%d].%s", i, tag);
2331 #if defined(YYBTYACC)
2332 else if (isalpha(c) || c == '_')
2334 char *arg = scan_id();
2335 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2336 if (arg == plhs[nrules]->argnames[i])
2339 unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr);
2340 fprintf(f, "yystack.l_mark[%d].%s", i - plhs[nrules]->args +
2347 dollar_error(d_lineno, d_line, d_cptr);
2349 else if (cptr[1] == '$')
2353 tag = plhs[nrules]->tag;
2356 fprintf(f, "yyval.%s", tag);
2359 fprintf(f, "yyval");
2361 #if defined(YYBTYACC)
2366 else if (isdigit(UCH(cptr[1])))
2370 if (havetags && offsets)
2372 if (i <= 0 || i > maxoffset)
2374 tag = rhs[offsets[i]]->tag;
2376 untyped_rhs(i, rhs[offsets[i]]->name);
2377 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2382 fprintf(f, "yystack.l_mark[%d]", -n);
2383 else if (i > maxoffset)
2385 dollar_warning(lineno, i);
2386 fprintf(f, "yystack.l_mark[%d]", i - maxoffset);
2389 fprintf(f, "yystack.l_mark[%d]", offsets[i]);
2393 else if (cptr[1] == '-')
2399 fprintf(f, "yystack.l_mark[%d]", -i - n);
2402 #if defined(YYBTYACC)
2403 else if (isalpha(cptr[1]) || cptr[1] == '_')
2408 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2409 if (arg == plhs[nrules]->argnames[i])
2412 unknown_arg_warning(lineno, "$", arg, line, cptr);
2413 tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]);
2414 fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n);
2416 fprintf(f, ".%s", tag);
2418 untyped_arg_warning(lineno, "$", arg);
2423 #if defined(YYBTYACC)
2428 int l_lineno = lineno;
2429 char *l_line = dup_line();
2430 char *l_cptr = l_line + (cptr - line);
2431 syntax_error(l_lineno, l_line, l_cptr);
2435 fprintf(f, "yyloc");
2439 else if (isdigit(UCH(cptr[1])))
2444 fprintf(f, "yystack.p_mark[%d]", -n);
2445 else if (i > maxoffset)
2447 at_warning(lineno, i);
2448 fprintf(f, "yystack.p_mark[%d]", i - maxoffset);
2451 fprintf(f, "yystack.p_mark[%d]", offsets[i]);
2456 if (isalpha(c) || c == '_' || c == '$')
2463 while (isalnum(c) || c == '_' || c == '$');
2467 #if defined(YYBTYACC)
2470 if (trialaction && c == L_BRAC && depth == 0)
2476 if (trialaction && c == R_BRAC && depth == 1)
2481 if (c == L_BRAC && !haveyyval)
2485 if (c == L_CURL && !haveyyval)
2487 fprintf(f, " if (!yytrial)\n");
2489 fprintf(f, line_format, lineno, input_file_name);
2493 fprintf(f, "\nbreak;\n");
2508 unterminated_action(a_lineno, a_line, a_cptr);
2513 fprintf(f, "\nbreak;\n");
2519 #if defined(YYBTYACC)
2538 #if defined(YYBTYACC)
2542 if (c == L_BRAC && !haveyyval)
2547 if (c == L_CURL && !haveyyval)
2549 fprintf(f, " if (!yytrial)\n");
2551 fprintf(f, line_format, lineno, input_file_name);
2556 fprintf(f, "\nbreak;\n");
2565 char *s = copy_string(c);
2573 char *s = copy_comment();
2584 #if defined(YYBTYACC)
2586 copy_destructor(void)
2592 struct mstring *destructor_text = msnew();
2599 msprintf(destructor_text, line_format, lineno, input_file_name);
2601 cptr = after_blanks(cptr);
2602 if (*cptr == L_CURL)
2603 /* avoid putting curly-braces in first column, to ease editing */
2604 mputc(destructor_text, '\t');
2606 syntax_error(lineno, line, cptr);
2609 a_line = dup_line();
2610 a_cptr = a_line + (cptr - line);
2619 int d_lineno = lineno;
2620 char *d_line = dup_line();
2621 char *d_cptr = d_line + (cptr - line);
2628 msprintf(destructor_text, "(*val).%s", tag);
2634 dollar_error(d_lineno, d_line, d_cptr);
2636 else if (cptr[1] == '$')
2638 /* process '$$' later; replacement is context dependent */
2639 msprintf(destructor_text, "$$");
2644 if (c == '@' && cptr[1] == '$')
2648 int l_lineno = lineno;
2649 char *l_line = dup_line();
2650 char *l_cptr = l_line + (cptr - line);
2651 syntax_error(l_lineno, l_line, l_cptr);
2653 msprintf(destructor_text, "(*loc)");
2657 if (isalpha(c) || c == '_' || c == '$')
2661 mputc(destructor_text, c);
2664 while (isalnum(c) || c == '_' || c == '$');
2668 mputc(destructor_text, c);
2675 unterminated_action(a_lineno, a_line, a_cptr);
2684 goto process_symbols;
2689 char *s = copy_string(c);
2690 msprintf(destructor_text, "%s", s);
2697 char *s = copy_comment();
2698 msprintf(destructor_text, "%s", s);
2707 code_text = msdone(destructor_text);
2716 { /* "no semantic type" default destructor */
2718 if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL)
2720 static char untyped_default[] = "<>";
2721 bp = make_bucket("untyped default");
2722 bp->tag = untyped_default;
2723 default_destructor[UNTYPED_DEFAULT] = bp;
2725 if (bp->destructor != NULL)
2726 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2728 /* replace "$$" with "(*val)" in destructor code */
2729 bp->destructor = process_destructor_XX(code_text, NULL);
2731 else if (cptr[1] == '*' && cptr[2] == '>')
2732 { /* "no per-symbol or per-type" default destructor */
2734 if ((bp = default_destructor[TYPED_DEFAULT]) == NULL)
2736 static char typed_default[] = "<*>";
2737 bp = make_bucket("typed default");
2738 bp->tag = typed_default;
2739 default_destructor[TYPED_DEFAULT] = bp;
2741 if (bp->destructor != NULL)
2742 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2745 /* postpone re-processing destructor $$s until end of grammar spec */
2746 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2747 NO_SPACE(bp->destructor);
2748 strcpy(bp->destructor, code_text);
2752 { /* "semantic type" default destructor */
2754 bp = lookup_type_destructor(tag);
2755 if (bp->destructor != NULL)
2756 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2758 /* replace "$$" with "(*val).tag" in destructor code */
2759 bp->destructor = process_destructor_XX(code_text, tag);
2762 else if (isalpha(c) || c == '_' || c == '.' || c == '$')
2763 { /* "symbol" destructor */
2765 if (bp->destructor != NULL)
2766 destructor_redeclared_warning(a_lineno, a_line, a_cptr);
2769 /* postpone re-processing destructor $$s until end of grammar spec */
2770 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
2771 NO_SPACE(bp->destructor);
2772 strcpy(bp->destructor, code_text);
2783 process_destructor_XX(char *code, char *tag)
2788 struct mstring *new_code = msnew();
2789 char *codeptr = code;
2792 loop: /* step thru code */
2794 if (c == '$' && codeptr[1] == '$')
2798 msprintf(new_code, "(*val)");
2800 msprintf(new_code, "(*val).%s", tag);
2803 if (isalpha(c) || c == '_' || c == '$')
2810 while (isalnum(c) || c == '_' || c == '$');
2824 return msdone(new_code);
2852 if (c == '*' && *codeptr == '/')
2854 mputc(new_code, '/');
2866 #endif /* defined(YYBTYACC) */
2875 if (c == '%' || c == '\\')
2883 else if ((c == 'p' || c == 'P') &&
2884 ((c = cptr[2]) == 'r' || c == 'R') &&
2885 ((c = cptr[3]) == 'e' || c == 'E') &&
2886 ((c = cptr[4]) == 'c' || c == 'C') &&
2887 ((c = cptr[5], !IS_IDENT(c))))
2890 syntax_error(lineno, line, cptr);
2893 if (isalpha(c) || c == '_' || c == '.' || c == '$')
2895 else if (c == '\'' || c == '"')
2899 syntax_error(lineno, line, cptr);
2902 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
2905 rprec[nrules] = bp->prec;
2906 rassoc[nrules] = bp->assoc;
2915 initialize_grammar();
2930 #if defined(YYBTYACC)
2931 else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC))
2933 else if (c == L_CURL || c == '=')
2939 start_rule(plhs[nrules - 1], 0);
2948 syntax_error(lineno, line, cptr);
2951 #if defined(YYBTYACC)
2953 start_requires_args(goal->name);
2965 for (i = 0; i < ntags; ++i)
2967 assert(tag_table[i]);
2979 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
2980 for (bp = first_symbol; bp; bp = bp->next)
2981 name_pool_size += strlen(bp->name) + 1;
2983 name_pool = TMALLOC(char, name_pool_size);
2984 NO_SPACE(name_pool);
2986 strcpy(name_pool, "$accept");
2987 strcpy(name_pool + 8, "$end");
2989 for (bp = first_symbol; bp; bp = bp->next)
2993 while ((*t++ = *s++) != 0)
3005 if (goal->class == UNKNOWN)
3006 undefined_goal(goal->name);
3008 for (bp = first_symbol; bp; bp = bp->next)
3010 if (bp->class == UNKNOWN)
3012 undefined_symbol_warning(bp->name);
3019 protect_string(char *src, char **des)
3032 if ('\\' == *s || '"' == *s)
3038 *des = d = TMALLOC(char, len);
3044 if ('\\' == *s || '"' == *s)
3058 #if defined(YYBTYACC)
3059 Value_t max_tok_pval;
3064 for (bp = first_symbol; bp; bp = bp->next)
3067 if (bp->class == TERM)
3070 start_symbol = (Value_t) ntokens;
3071 nvars = (Value_t) (nsyms - ntokens);
3073 symbol_name = TMALLOC(char *, nsyms);
3074 NO_SPACE(symbol_name);
3076 symbol_value = TMALLOC(Value_t, nsyms);
3077 NO_SPACE(symbol_value);
3079 symbol_prec = TMALLOC(Value_t, nsyms);
3080 NO_SPACE(symbol_prec);
3082 symbol_assoc = TMALLOC(char, nsyms);
3083 NO_SPACE(symbol_assoc);
3085 #if defined(YYBTYACC)
3086 symbol_pval = TMALLOC(Value_t, nsyms);
3087 NO_SPACE(symbol_pval);
3091 symbol_destructor = CALLOC(sizeof(char *), nsyms);
3092 NO_SPACE(symbol_destructor);
3094 symbol_type_tag = CALLOC(sizeof(char *), nsyms);
3095 NO_SPACE(symbol_type_tag);
3099 v = TMALLOC(bucket *, nsyms);
3103 v[start_symbol] = 0;
3106 j = (Value_t) (start_symbol + 1);
3107 for (bp = first_symbol; bp; bp = bp->next)
3109 if (bp->class == TERM)
3114 assert(i == ntokens && j == nsyms);
3116 for (i = 1; i < ntokens; ++i)
3119 goal->index = (Index_t) (start_symbol + 1);
3120 k = (Value_t) (start_symbol + 2);
3130 for (i = (Value_t) (start_symbol + 1); i < nsyms; ++i)
3140 for (i = 1; i < ntokens; ++i)
3145 for (j = k++; j > 0 && symbol_value[j - 1] > n; --j)
3146 symbol_value[j] = symbol_value[j - 1];
3147 symbol_value[j] = n;
3153 if (v[1]->value == UNDEFINED)
3158 for (i = 2; i < ntokens; ++i)
3160 if (v[i]->value == UNDEFINED)
3162 while (j < k && n == symbol_value[j])
3164 while (++j < k && n == symbol_value[j])
3173 symbol_name[0] = name_pool + 8;
3174 symbol_value[0] = 0;
3176 symbol_assoc[0] = TOKEN;
3177 #if defined(YYBTYACC)
3181 for (i = 1; i < ntokens; ++i)
3183 symbol_name[i] = v[i]->name;
3184 symbol_value[i] = v[i]->value;
3185 symbol_prec[i] = v[i]->prec;
3186 symbol_assoc[i] = v[i]->assoc;
3187 #if defined(YYBTYACC)
3188 symbol_pval[i] = v[i]->value;
3189 if (symbol_pval[i] > max_tok_pval)
3190 max_tok_pval = symbol_pval[i];
3193 symbol_destructor[i] = v[i]->destructor;
3194 symbol_type_tag[i] = v[i]->tag;
3198 symbol_name[start_symbol] = name_pool;
3199 symbol_value[start_symbol] = -1;
3200 symbol_prec[start_symbol] = 0;
3201 symbol_assoc[start_symbol] = TOKEN;
3202 #if defined(YYBTYACC)
3203 symbol_pval[start_symbol] = (Value_t) (max_tok_pval + 1);
3205 for (++i; i < nsyms; ++i)
3208 symbol_name[k] = v[i]->name;
3209 symbol_value[k] = v[i]->value;
3210 symbol_prec[k] = v[i]->prec;
3211 symbol_assoc[k] = v[i]->assoc;
3212 #if defined(YYBTYACC)
3213 symbol_pval[k] = (Value_t) ((max_tok_pval + 1) + v[i]->value + 1);
3216 symbol_destructor[k] = v[i]->destructor;
3217 symbol_type_tag[k] = v[i]->tag;
3224 symbol_pname = TMALLOC(char *, nsyms);
3225 NO_SPACE(symbol_pname);
3227 for (i = 0; i < nsyms; ++i)
3228 protect_string(symbol_name[i], &(symbol_pname[i]));
3242 ritem = TMALLOC(Value_t, nitems);
3245 rlhs = TMALLOC(Value_t, nrules);
3248 rrhs = TMALLOC(Value_t, nrules + 1);
3251 rprec = TREALLOC(Value_t, rprec, nrules);
3254 rassoc = TREALLOC(Assoc_t, rassoc, nrules);
3258 ritem[1] = goal->index;
3263 rlhs[2] = start_symbol;
3269 for (i = 3; i < nrules; ++i)
3271 #if defined(YYBTYACC)
3272 if (plhs[i]->args > 0)
3274 if (plhs[i]->argnames)
3276 FREE(plhs[i]->argnames);
3277 plhs[i]->argnames = NULL;
3279 if (plhs[i]->argtags)
3281 FREE(plhs[i]->argtags);
3282 plhs[i]->argtags = NULL;
3285 #endif /* defined(YYBTYACC) */
3286 rlhs[i] = plhs[i]->index;
3292 ritem[j] = pitem[j]->index;
3293 if (pitem[j]->class == TERM)
3295 prec2 = pitem[j]->prec;
3296 assoc = pitem[j]->assoc;
3300 ritem[j] = (Value_t) - i;
3302 if (rprec[i] == UNDEFINED)
3312 #if defined(YYBTYACC)
3321 size_t j, spacing = 0;
3322 FILE *f = verbose_file;
3328 for (i = 2; i < nrules; ++i)
3330 if (rlhs[i] != rlhs[i - 1])
3334 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
3335 spacing = strlen(symbol_name[rlhs[i]]) + 1;
3339 fprintf(f, "%4d ", i - 2);
3346 while (ritem[k] >= 0)
3348 fprintf(f, " %s", symbol_name[ritem[k]]);
3356 #if defined(YYBTYACC)
3358 finalize_destructors(void)
3364 for (i = 2; i < nsyms; ++i)
3366 tag = symbol_type_tag[i];
3367 if (symbol_destructor[i] == NULL)
3370 { /* use <> destructor, if there is one */
3371 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3373 symbol_destructor[i] = TMALLOC(char,
3374 strlen(bp->destructor) + 1);
3375 NO_SPACE(symbol_destructor[i]);
3376 strcpy(symbol_destructor[i], bp->destructor);
3380 { /* use type destructor for this tag, if there is one */
3381 bp = lookup_type_destructor(tag);
3382 if (bp->destructor != NULL)
3384 symbol_destructor[i] = TMALLOC(char,
3385 strlen(bp->destructor) + 1);
3386 NO_SPACE(symbol_destructor[i]);
3387 strcpy(symbol_destructor[i], bp->destructor);
3390 { /* use <*> destructor, if there is one */
3391 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3392 /* replace "$$" with "(*val).tag" in destructor code */
3393 symbol_destructor[i]
3394 = process_destructor_XX(bp->destructor, tag);
3399 { /* replace "$$" with "(*val)[.tag]" in destructor code */
3400 symbol_destructor[i]
3401 = process_destructor_XX(symbol_destructor[i], tag);
3404 /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */
3405 DO_FREE(symbol_type_tag); /* no longer needed */
3406 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3409 /* 'bp->tag' is a static value, don't free */
3410 FREE(bp->destructor);
3413 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3416 /* 'bp->tag' is a static value, don't free */
3417 FREE(bp->destructor);
3420 if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL)
3427 /* 'bp->tag' freed by 'free_tags()' */
3428 FREE(bp->destructor);
3433 #endif /* defined(YYBTYACC) */
3438 write_section(code_file, banner);
3439 create_symbol_table();
3440 read_declarations();
3442 free_symbol_table();
3449 #if defined(YYBTYACC)
3451 finalize_destructors();
3458 free_declarations(param * list)
3462 param *next = list->next;
3475 lex_param = free_declarations(lex_param);
3476 parse_param = free_declarations(parse_param);
3486 DO_FREE(symbol_name);
3487 DO_FREE(symbol_prec);
3488 DO_FREE(symbol_assoc);
3489 DO_FREE(symbol_value);
3490 #if defined(YYBTYACC)
3491 DO_FREE(symbol_pval);
3492 DO_FREE(symbol_destructor);
3493 DO_FREE(symbol_type_tag);