-/* $Id: reader.c,v 1.57 2014/10/06 00:52:44 tom Exp $ */
+/* $Id: reader.c,v 1.84 2020/09/10 20:26:13 tom Exp $ */
#include "defs.h"
/* The line size must be a positive integer. One hundred was chosen */
/* because few lines in Yacc input grammars exceed 100 characters. */
/* Note that if a line exceeds LINESIZE characters, the line buffer */
-/* will be expanded to accomodate it. */
+/* will be expanded to accommodate it. */
#define LINESIZE 100
static void start_rule(bucket *bp, int s_lineno);
#if defined(YYBTYACC)
+static void copy_initial_action(void);
static void copy_destructor(void);
static char *process_destructor_XX(char *code, char *tag);
#endif
+#define CACHE_SIZE 256
static char *cache;
static int cinc, cache_size;
static Value_t prec;
static int gensym;
static char last_was_action;
+#if defined(YYBTYACC)
+static int trialaction;
+#endif
static int maxitems;
static bucket **pitem;
param *lex_param;
param *parse_param;
+static const char *code_keys[] =
+{
+ "", "requires", "provides", "top", "imports",
+};
+
+struct code_lines code_lines[CODE_MAX];
+
#if defined(YYBTYACC)
int destructor = 0; /* =1 if at least one %destructor */
assert(cinc >= 0);
if (cinc >= cache_size)
{
- cache_size += 256;
+ cache_size += CACHE_SIZE;
cache = TREALLOC(char, cache, cache_size);
NO_SPACE(cache);
}
++cinc;
}
-static void
-get_line(void)
+typedef enum
{
- FILE *f = input_file;
- int c;
- int i;
+ ldSPC1,
+ ldSPC2,
+ ldNAME,
+ ldSPC3,
+ ldNUM,
+ ldSPC4,
+ ldFILE,
+ ldOK,
+ ldERR
+}
+LINE_DIR;
- if (saw_eof || (c = getc(f)) == EOF)
+/*
+ * Expect this pattern:
+ * /^[[:space:]]*#[[:space:]]*
+ * line[[:space:]]+
+ * [[:digit:]]+
+ * ([[:space:]]*|[[:space:]]+"[^"]+")/
+ */
+static int
+line_directive(void)
+{
+#define UNLESS(what) if (what) { ld = ldERR; break; }
+ int n;
+ int line_1st = -1;
+ int name_1st = -1;
+ int name_end = -1;
+ LINE_DIR ld = ldSPC1;
+ for (n = 0; (ld <= ldOK) && (line[n] != '\0'); ++n)
{
- if (line)
+ int ch = UCH(line[n]);
+ switch (ld)
{
- FREE(line);
- line = 0;
+ case ldSPC1:
+ if (isspace(UCH(ch)))
+ {
+ break;
+ }
+ else
+ UNLESS(ch != '#');
+ ld = ldSPC2;
+ break;
+ case ldSPC2:
+ if (isspace(UCH(ch)))
+ {
+ break;
+ }
+ /* FALLTHRU */
+ case ldNAME:
+ UNLESS(strncmp(line + n, "line", 4));
+ n += 4;
+ if (line[n] == '\0')
+ {
+ ld = ldOK;
+ break;
+ }
+ else
+ UNLESS(!isspace(UCH(line[n])));
+ ld = ldSPC3;
+ break;
+ case ldSPC3:
+ if (isspace(UCH(ch)))
+ {
+ break;
+ }
+ else
+ UNLESS(!isdigit(UCH(ch)));
+ line_1st = n;
+ ld = ldNUM; /* this is needed, but cppcheck says no... */
+ /* FALLTHRU */
+ case ldNUM:
+ if (isdigit(UCH(ch)))
+ {
+ break;
+ }
+ else
+ UNLESS(!isspace(UCH(ch)));
+ ld = ldSPC4;
+ break;
+ case ldSPC4:
+ if (isspace(UCH(ch)))
+ {
+ break;
+ }
+ else
+ UNLESS(ch != '"');
+ UNLESS(line[n + 1] == '"');
+ ld = ldFILE;
+ name_1st = n;
+ break;
+ case ldFILE:
+ if (ch != '"')
+ {
+ break;
+ }
+ ld = ldOK;
+ name_end = n;
+ /* FALLTHRU */
+ case ldERR:
+ case ldOK:
+ break;
}
- cptr = 0;
- saw_eof = 1;
- return;
}
- if (line == 0 || linesize != (LINESIZE + 1))
+ if (ld == ldOK)
{
- if (line)
- FREE(line);
- linesize = LINESIZE + 1;
- line = TCMALLOC(char, linesize);
- NO_SPACE(line);
+ size_t need = (size_t) (name_end - name_1st);
+ if ((long)need > (long)input_file_name_len)
+ {
+ input_file_name_len = ((need + 1) * 3) / 2;
+ input_file_name = TREALLOC(char, input_file_name, input_file_name_len);
+ NO_SPACE(input_file_name);
+ }
+ if ((long)need > 0)
+ {
+ memcpy(input_file_name, line + name_1st + 1, need - 1);
+ input_file_name[need - 1] = '\0';
+ }
+ else
+ {
+ input_file_name[0] = '\0';
+ }
}
- i = 0;
- ++lineno;
- for (;;)
+ if (ld >= ldNUM && ld < ldERR)
{
- line[i] = (char)c;
- if (c == '\n')
- break;
- if (++i >= linesize)
+ if (line_1st >= 0)
{
- linesize += LINESIZE;
- line = TREALLOC(char, line, linesize);
- NO_SPACE(line);
+ lineno = (int)strtol(line + line_1st, NULL, 10) - 1;
}
- c = getc(f);
- if (c == EOF)
+ else
+ {
+ lineno = 0;
+ }
+ }
+
+ return (ld == ldOK);
+#undef UNLESS
+}
+
+static void
+get_line(void)
+{
+ FILE *f = input_file;
+
+ do
+ {
+ int c;
+ int i;
+
+ if (saw_eof || (c = getc(f)) == EOF)
{
- line[i] = '\n';
+ if (line)
+ {
+ FREE(line);
+ line = 0;
+ }
+ cptr = 0;
saw_eof = 1;
- break;
+ return;
}
+
+ if (line == NULL || linesize != (LINESIZE + 1))
+ {
+ if (line)
+ FREE(line);
+ linesize = LINESIZE + 1;
+ line = TMALLOC(char, linesize);
+ NO_SPACE(line);
+ }
+
+ i = 0;
+ ++lineno;
+ for (;;)
+ {
+ line[i++] = (char)c;
+ if (c == '\n')
+ break;
+ if ((i + 3) >= linesize)
+ {
+ linesize += LINESIZE;
+ line = TREALLOC(char, line, linesize);
+ NO_SPACE(line);
+ }
+ c = getc(f);
+ if (c == EOF)
+ {
+ line[i++] = '\n';
+ saw_eof = 1;
+ break;
+ }
+ }
+ line[i] = '\0';
}
+ while (line_directive());
cptr = line;
return;
}
{
char *p, *s, *t;
- if (line == 0)
- return (0);
+ if (line == NULL)
+ return (NULL);
s = line;
while (*s != '\n')
++s;
skip_comment(void)
{
char *s;
-
- int st_lineno = lineno;
- char *st_line = dup_line();
- char *st_cptr = st_line + (cptr - line);
+ struct ainfo a;
+ a.a_lineno = lineno;
+ a.a_line = dup_line();
+ a.a_cptr = a.a_line + (cptr - line);
s = cptr + 2;
for (;;)
if (*s == '*' && s[1] == '/')
{
cptr = s + 2;
- FREE(st_line);
+ FREE(a.a_line);
return;
}
if (*s == '\n')
{
get_line();
- if (line == 0)
- unterminated_comment(st_lineno, st_line, st_cptr);
+ if (line == NULL)
+ unterminated_comment(&a);
s = cptr;
}
else
{
char *s;
- if (line == 0)
+ if (line == NULL)
{
get_line();
- if (line == 0)
+ if (line == NULL)
return (EOF);
}
else if (s[1] == '/')
{
get_line();
- if (line == 0)
+ if (line == NULL)
return (EOF);
s = cptr;
break;
/* *INDENT-OFF* */
static struct keyword
{
- char name[13];
+ char name[16];
int token;
}
keywords[] = {
{ "binary", NONASSOC },
+ { "code", XCODE },
+ { "debug", XXXDEBUG },
#if defined(YYBTYACC)
{ "destructor", DESTRUCTOR },
#endif
+ { "error-verbose",ERROR_VERBOSE },
{ "expect", EXPECT },
{ "expect-rr", EXPECT_RR },
- { "ident", IDENT },
+ { "ident", IDENT },
+#if defined(YYBTYACC)
+ { "initial-action", INITIAL_ACTION },
+#endif
{ "left", LEFT },
{ "lex-param", LEX_PARAM },
#if defined(YYBTYACC)
{ "nonassoc", NONASSOC },
{ "parse-param", PARSE_PARAM },
{ "pure-parser", PURE_PARSER },
- { "right", RIGHT },
+ { "right", RIGHT },
{ "start", START },
- { "term", TOKEN },
- { "token", TOKEN },
- { "token-table", TOKEN_TABLE },
+ { "term", TOKEN },
+ { "token", TOKEN },
+ { "token-table", TOKEN_TABLE },
{ "type", TYPE },
{ "union", UNION },
{ "yacc", POSIX_YACC },
{
int c;
char *t_cptr = cptr;
- struct keyword *key;
c = *++cptr;
- if (isalpha(c))
+ if (isalpha(UCH(c)))
{
+ struct keyword *key;
+
cinc = 0;
for (;;)
{
- if (isalpha(c))
+ if (isalpha(UCH(c)))
{
- if (isupper(c))
+ if (isupper(UCH(c)))
c = tolower(c);
cachec(c);
}
- else if (isdigit(c)
+ else if (isdigit(UCH(c))
|| c == '-'
|| c == '.'
|| c == '$')
return (NONASSOC);
}
syntax_error(lineno, line, t_cptr);
+ /*NOTREACHED */
}
static void
copy_string(int quote)
{
struct mstring *temp = msnew();
- int c;
- int s_lineno = lineno;
- char *s_line = dup_line();
- char *s_cptr = s_line + (cptr - line - 1);
+ struct ainfo a;
+ a.a_lineno = lineno;
+ a.a_line = dup_line();
+ a.a_cptr = a.a_line + (cptr - line - 1);
for (;;)
{
- c = *cptr++;
+ int c = *cptr++;
+
mputc(temp, c);
if (c == quote)
{
- FREE(s_line);
+ FREE(a.a_line);
return msdone(temp);
}
if (c == '\n')
- unterminated_string(s_lineno, s_line, s_cptr);
+ unterminated_string(&a);
if (c == '\\')
{
c = *cptr++;
if (c == '\n')
{
get_line();
- if (line == 0)
- unterminated_string(s_lineno, s_line, s_cptr);
+ if (line == NULL)
+ unterminated_string(&a);
}
}
}
}
else if (c == '*')
{
- int c_lineno = lineno;
- char *c_line = dup_line();
- char *c_cptr = c_line + (cptr - line - 1);
+ struct ainfo a;
+ a.a_lineno = lineno;
+ a.a_line = dup_line();
+ a.a_cptr = a.a_line + (cptr - line - 1);
mputc(temp, c);
++cptr;
{
mputc(temp, '/');
++cptr;
- FREE(c_line);
+ FREE(a.a_line);
return msdone(temp);
}
if (c == '\n')
{
get_line();
- if (line == 0)
- unterminated_comment(c_lineno, c_line, c_cptr);
+ if (line == NULL)
+ unterminated_comment(&a);
}
}
}
return msdone(temp);
}
+static int
+check_key(int pos)
+{
+ const char *key = code_keys[pos];
+ while (*cptr && *key)
+ if (*key++ != *cptr++)
+ return 0;
+ if (*key || (!isspace(UCH(*cptr)) && *cptr != L_CURL))
+ return 0;
+ cptr--;
+ return 1;
+}
+
+static void
+copy_code(void)
+{
+ int c;
+ int curl;
+ int cline;
+ int on_line = 0;
+ int pos = CODE_HEADER;
+ struct mstring *code_mstr;
+
+ /* read %code <keyword> { */
+ for (;;)
+ {
+ c = *++cptr;
+ if (c == EOF)
+ unexpected_EOF();
+ if (isspace(UCH(c)))
+ continue;
+
+ if (c == L_CURL)
+ break;
+
+ if (pos == CODE_HEADER)
+ {
+ switch (UCH(c))
+ {
+ case 'r':
+ pos = CODE_REQUIRES;
+ break;
+ case 'p':
+ pos = CODE_PROVIDES;
+ break;
+ case 't':
+ pos = CODE_TOP;
+ break;
+ case 'i':
+ pos = CODE_IMPORTS;
+ break;
+ default:
+ break;
+ }
+
+ if (pos == -1 || !check_key(pos))
+ {
+ syntax_error(lineno, line, cptr);
+ /*NOTREACHED */
+ }
+ }
+ }
+
+ cptr++; /* skip initial curl */
+ while (*cptr && isspace(UCH(*cptr))) /* skip space */
+ cptr++;
+ curl = 1; /* nesting count */
+
+ /* gather text */
+ code_lines[pos].name = code_keys[pos];
+ if ((cline = (int)code_lines[pos].num) != 0)
+ {
+ code_mstr = msrenew(code_lines[pos].lines);
+ }
+ else
+ {
+ code_mstr = msnew();
+ }
+ cline++;
+ msprintf(code_mstr, line_format, lineno, input_file_name);
+ for (;;)
+ {
+ c = *cptr++;
+ switch (c)
+ {
+ case '\0':
+ get_line();
+ if (line == NULL)
+ {
+ unexpected_EOF();
+ /*NOTREACHED */
+ }
+ continue;
+ case '\n':
+ cline++;
+ on_line = 0;
+ break;
+ case L_CURL:
+ curl++;
+ break;
+ case R_CURL:
+ if (--curl == 0)
+ {
+ if (on_line > 1)
+ {
+ mputc(code_mstr, '\n');
+ cline++;
+ }
+ code_lines[pos].lines = msdone(code_mstr);
+ code_lines[pos].num = (size_t) cline;
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ mputc(code_mstr, c);
+ on_line++;
+ }
+}
+
static void
copy_text(void)
{
int c;
FILE *f = text_file;
int need_newline = 0;
- int t_lineno = lineno;
- char *t_line = dup_line();
- char *t_cptr = t_line + (cptr - line - 2);
+ struct ainfo a;
+ a.a_lineno = lineno;
+ a.a_line = dup_line();
+ a.a_cptr = a.a_line + (cptr - line - 2);
if (*cptr == '\n')
{
get_line();
- if (line == 0)
- unterminated_text(t_lineno, t_line, t_cptr);
+ if (line == NULL)
+ unterminated_text(&a);
}
if (!lflag)
fprintf(f, line_format, lineno, input_file_name);
get_line();
if (line)
goto loop;
- unterminated_text(t_lineno, t_line, t_cptr);
+ unterminated_text(&a);
case '\'':
case '"':
if (need_newline)
putc('\n', f);
++cptr;
- FREE(t_line);
+ FREE(a.a_line);
return;
}
/* FALLTHRU */
{
int c;
int depth;
- int u_lineno = lineno;
- char *u_line = dup_line();
- char *u_cptr = u_line + (cptr - line - 6);
+ struct ainfo a;
+ a.a_lineno = lineno;
+ a.a_line = dup_line();
+ a.a_cptr = a.a_line + (cptr - line - 6);
if (unionized)
over_unionized(cptr - 6);
unionized = 1;
- if (!lflag)
- fprintf(text_file, line_format, lineno, input_file_name);
-
puts_both("#ifdef YYSTYPE\n");
puts_both("#undef YYSTYPE_IS_DECLARED\n");
puts_both("#define YYSTYPE_IS_DECLARED 1\n");
puts_both("#endif\n");
puts_both("#ifndef YYSTYPE_IS_DECLARED\n");
puts_both("#define YYSTYPE_IS_DECLARED 1\n");
+
+ if (!lflag)
+ fprintf(text_file, line_format, lineno, input_file_name);
puts_both("typedef union");
depth = 0;
{
case '\n':
get_line();
- if (line == 0)
- unterminated_union(u_lineno, u_line, u_cptr);
+ if (line == NULL)
+ unterminated_union(&a);
goto loop;
case L_CURL:
{
puts_both(" YYSTYPE;\n");
puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n");
- FREE(u_line);
+ FREE(a.a_line);
return;
}
goto loop;
{
buf_size = (size_t) linesize;
buf = TMALLOC(char, buf_size);
+ NO_SPACE(buf);
}
else if (c == '\n')
{
+ char *tmp;
+
get_line();
- if (line == 0)
+ if (line == NULL)
unexpected_EOF();
--cptr;
buf_size += (size_t) linesize;
- buf = TREALLOC(char, buf, buf_size);
+ tmp = TREALLOC(char, buf, buf_size);
+ NO_SPACE(tmp);
+ buf = tmp;
}
- NO_SPACE(buf);
if (curly)
{
if ((state == 2) && (c == L_CURL))
goto oops;
}
- buf[i--] = '\0';
- i = trim_blanks(buf);
+ buf[++i] = '\0';
+ (void)trim_blanks(buf);
comma = buf - 1;
do
if (parms[i] == ']')
{
int level = 1;
- while (i >= 0 && level > 0 && parms[i] != '[')
+ while (i >= 0)
{
- if (parms[i] == ']')
+ char ch = parms[i--];
+ if (ch == ']')
+ {
++level;
- else if (parms[i] == '[')
- --level;
- i--;
+ }
+ else if (ch == '[')
+ {
+ if (--level <= 1)
+ {
+ ++i;
+ break;
+ }
+ }
}
if (i <= 0)
unexpected_EOF();
int n;
char *s;
bucket *bp;
- int s_lineno = lineno;
- char *s_line = dup_line();
- char *s_cptr = s_line + (cptr - line);
+ struct ainfo a;
+ a.a_lineno = lineno;
+ a.a_line = dup_line();
+ a.a_cptr = a.a_line + (cptr - line);
quote = *cptr++;
cinc = 0;
if (c == quote)
break;
if (c == '\n')
- unterminated_string(s_lineno, s_line, s_cptr);
+ unterminated_string(&a);
if (c == '\\')
{
char *c_cptr = cptr - 1;
{
case '\n':
get_line();
- if (line == 0)
- unterminated_string(s_lineno, s_line, s_cptr);
+ if (line == NULL)
+ unterminated_string(&a);
continue;
case '0':
}
cachec(c);
}
- FREE(s_line);
+ FREE(a.a_line);
n = cinc;
s = TMALLOC(char, n);
cachec('\\');
cachec(c);
}
- else if (isprint(c))
+ else if (isprint(UCH(c)))
cachec(c);
else
{
static int
is_reserved(char *name)
{
- char *s;
-
if (strcmp(name, ".") == 0 ||
strcmp(name, "$accept") == 0 ||
strcmp(name, "$end") == 0)
if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2])))
{
- s = name + 3;
+ char *s = name + 3;
+
while (isdigit(UCH(*s)))
++s;
if (*s == NUL)
get_number(void)
{
int c;
- Value_t n;
+ long n;
+ char *base = cptr;
n = 0;
- for (c = *cptr; isdigit(c); c = *++cptr)
- n = (Value_t) (10 * n + (c - '0'));
+ for (c = *cptr; isdigit(UCH(c)); c = *++cptr)
+ {
+ n = (10 * n + (c - '0'));
+ if (n > MAXYYINT)
+ {
+ syntax_error(lineno, line, base);
+ /*NOTREACHED */
+ }
+ }
- return (n);
+ return (Value_t)(n);
}
static char *
c = nextc();
if (c == EOF)
unexpected_EOF();
- if (!isalpha(c) && c != '_' && c != '$')
+ if (!IS_NAME1(c))
illegal_tag(t_lineno, t_line, t_cptr);
cinc = 0;
{
char *b = cptr;
- while (isalnum(*cptr) || *cptr == '_' || *cptr == '$')
+ while (IS_NAME2(UCH(*cptr)))
cptr++;
return cache_tag(b, (size_t) (cptr - b));
}
for (;;)
{
- if (isalpha(c) || c == '_' || c == '.' || c == '$')
+ if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
bp = get_name();
else if (c == '\'' || c == '"')
bp = get_literal();
{
if (bp->prec && prec != bp->prec)
reprec_warning(bp->name);
- bp->assoc = (Assoc_t) assoc;
+ bp->assoc = (Assoc_t)assoc;
bp->prec = prec;
}
if (c == EOF)
unexpected_EOF();
- if (isdigit(c))
+ if (isdigit(UCH(c)))
{
value = get_number();
if (bp->value != UNDEFINED && value != bp->value)
for (;;)
{
- if (isdigit(c))
+ if (isdigit(UCH(c)))
{
if (assoc == EXPECT)
SRexpect = get_number();
* Spaces, tabs, and numbers are ok,
* words, punc., etc. are syntax errors.
*/
- else if (c == '\n' || isalpha(c) || !isspace(c))
+ else if (c == '\n' || isalpha(UCH(c)) || !isspace(UCH(c)))
{
syntax_error(lineno, line, cptr);
}
declare_argtypes(bucket *bp)
{
char *tags[MAXARGS];
- int args = 0, c;
+ int args = 0;
if (bp->args >= 0)
retyped_warning(bp->name);
cptr++; /* skip open paren */
for (;;)
{
- c = nextc();
+ int c = nextc();
if (c == EOF)
unexpected_EOF();
if (c != '<')
declare_types(void)
{
int c;
- bucket *bp;
+ bucket *bp = NULL;
char *tag = NULL;
c = nextc();
c = nextc();
if (c == EOF)
unexpected_EOF();
- if (isalpha(c) || c == '_' || c == '.' || c == '$')
+ if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
{
bp = get_name();
#if defined(YYBTYACC)
c = nextc();
if (c == EOF)
unexpected_EOF();
- if (!isalpha(c) && c != '_' && c != '.' && c != '$')
+ if (!isalpha(UCH(c)) && c != '_' && c != '.' && c != '$')
syntax_error(lineno, line, cptr);
bp = get_name();
if (bp->class == TERM)
static void
read_declarations(void)
{
- int c, k;
-
- cache_size = 256;
+ cache_size = CACHE_SIZE;
cache = TMALLOC(char, cache_size);
NO_SPACE(cache);
for (;;)
{
- c = nextc();
+ int k;
+ int c = nextc();
+
if (c == EOF)
unexpected_EOF();
if (c != '%')
copy_ident();
break;
+ case XCODE:
+ copy_code();
+ break;
+
case TEXT:
copy_text();
break;
token_table = 1;
break;
+ case ERROR_VERBOSE:
+ error_verbose = 1;
+ break;
+
#if defined(YYBTYACC)
case LOCATIONS:
locations = 1;
destructor = 1;
copy_destructor();
break;
+ case INITIAL_ACTION:
+ copy_initial_action();
+ break;
#endif
+ case XXXDEBUG:
+ /* XXX: FIXME */
+ break;
+
case POSIX_YACC:
/* noop for bison compatibility. byacc is already designed to be posix
* yacc compatible. */
struct mstring *s = msnew();
int depth = 0, len = 1;
char c, quote = 0;
- int a_lineno = lineno;
- char *a_line = dup_line();
- char *a_cptr = a_line + (cptr - line - 1);
+ struct ainfo a;
+
+ a.a_lineno = lineno;
+ a.a_line = dup_line();
+ a.a_cptr = a.a_line + (cptr - line - 1);
while ((c = *cptr++) != R_PAREN || depth || quote)
{
if (!line)
{
if (quote)
- unterminated_string(a_lineno, a_line, a_cptr);
+ unterminated_string(&a);
else
- unterminated_arglist(a_lineno, a_line, a_cptr);
+ unterminated_arglist(&a);
}
}
else if (quote)
}
if (alen)
*alen = len;
- FREE(a_line);
+ FREE(a.a_line);
return msdone(s);
}
{
char *b;
- while (isspace(*p))
+ while (isspace(UCH(*p)))
if (*p++ == '\n')
rescan_lineno++;
- if (!isalpha(*p) && *p != '_')
+ if (!isalpha(UCH(*p)) && *p != '_')
return NULL;
b = p;
- while (isalnum(*p) || *p == '_' || *p == '$')
+ while (IS_NAME2(UCH(*p)))
p++;
if (save)
{
{
int neg = 0, val = 0;
- while (isspace(*p))
+ while (isspace(UCH(*p)))
if (*p++ == '\n')
rescan_lineno++;
if (*p == '-')
neg = 1;
p++;
}
- if (!isdigit(*p))
+ if (!isdigit(UCH(*p)))
return NULL;
- while (isdigit(*p))
+ while (isdigit(UCH(*p)))
val = val * 10 + *p++ - '0';
if (neg)
val = -val;
char *p = args, *tmp;
int i, redec = 0;
- if (a->args > 0)
+ if (a->args >= 0)
{
if (a->args != argslen)
arg_number_disagree_warning(rescan_lineno, a->name);
return;
for (i = 0; i < argslen; i++)
{
- while (isspace(*p))
+ while (isspace(UCH(*p)))
if (*p++ == '\n')
rescan_lineno++;
if (*p++ != '$')
bad_formals();
- while (isspace(*p))
+ while (isspace(UCH(*p)))
if (*p++ == '\n')
rescan_lineno++;
if (*p == '<')
havetags = 1;
if (!(p = parse_id(p + 1, &tmp)))
bad_formals();
- while (isspace(*p))
+ while (isspace(UCH(*p)))
if (*p++ == '\n')
rescan_lineno++;
if (*p++ != '>')
a->argtags[i] = NULL;
if (!(p = parse_id(p, &a->argnames[i])))
bad_formals();
- while (isspace(*p))
+ while (isspace(UCH(*p)))
if (*p++ == '\n')
rescan_lineno++;
if (*p++)
{
char *p = *theptr;
struct mstring *c = msnew();
- int i, j, n;
+ int i, n;
Value_t *offsets = NULL, maxoffset;
bucket **rhs;
}
if (maxoffset > 0)
{
+ int j;
+
offsets = TMALLOC(Value_t, maxoffset + 1);
NO_SPACE(offsets);
for (j = 0, i++; i < nitems; i++)
if (pitem[i]->class != ARGUMENT)
- offsets[++j] = (Value_t) (i - nitems + 1);
+ offsets[++j] = (Value_t)(i - nitems + 1);
}
rhs = pitem + nitems - 1;
if (*++p == '<')
if (!(p = parse_id(++p, &tag)) || *p++ != '>')
illegal_tag(rescan_lineno, NULL, NULL);
- if (isdigit(*p) || *p == '-')
+ if (isdigit(UCH(*p)) || *p == '-')
{
int val;
if (!(p = parse_int(p, &val)))
else if (havetags)
unknown_rhs(val);
}
- else if (isalpha(*p) || *p == '_')
+ else if (isalpha(UCH(*p)) || *p == '_')
{
char *arg;
if (!(p = parse_id(p, &arg)))
unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL);
else if (!tag)
tag = plhs[nrules]->argtags[i];
- msprintf(c, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1
- - n);
+ msprintf(c, "yystack.l_mark[%d]",
+ i - plhs[nrules]->args + 1 - n);
if (tag)
msprintf(c, ".%s", tag);
else if (havetags)
return msdone(c);
}
+static int
+can_elide_arg(char **theptr, char *yyvaltag)
+{
+ char *p = *theptr;
+ int rv = 0;
+ int i, n = 0;
+ Value_t *offsets = NULL, maxoffset = 0;
+ bucket **rhs;
+ char *tag = 0;
+
+ if (*p++ != '$')
+ return 0;
+ if (*p == '<')
+ {
+ if (!(p = parse_id(++p, &tag)) || *p++ != '>')
+ return 0;
+ }
+ for (i = nitems - 1; pitem[i]; --i)
+ {
+ n++;
+ if (pitem[i]->class != ARGUMENT)
+ maxoffset++;
+ }
+ if (maxoffset > 0)
+ {
+ int j;
+
+ offsets = TMALLOC(Value_t, maxoffset + 1);
+ NO_SPACE(offsets);
+
+ for (j = 0, i++; i < nitems; i++)
+ if (pitem[i]->class != ARGUMENT)
+ offsets[++j] = (Value_t)(i - nitems + 1);
+ }
+ rhs = pitem + nitems - 1;
+
+ if (isdigit(UCH(*p)) || *p == '-')
+ {
+ int val;
+ if (!(p = parse_int(p, &val)))
+ rv = 0;
+ else
+ {
+ if (val <= 0)
+ rv = 1 - val + n;
+ else if (val > maxoffset)
+ rv = 0;
+ else
+ {
+ i = offsets[val];
+ rv = 1 - i;
+ if (!tag)
+ tag = rhs[i]->tag;
+ }
+ }
+ }
+ else if (isalpha(UCH(*p)) || *p == '_')
+ {
+ char *arg;
+ if (!(p = parse_id(p, &arg)))
+ {
+ FREE(offsets);
+ return 0;
+ }
+ for (i = plhs[nrules]->args - 1; i >= 0; i--)
+ if (arg == plhs[nrules]->argnames[i])
+ break;
+ if (i >= 0)
+ {
+ if (!tag)
+ tag = plhs[nrules]->argtags[i];
+ rv = plhs[nrules]->args + n - i;
+ }
+ }
+ if (tag && yyvaltag)
+ {
+ if (strcmp(tag, yyvaltag))
+ rv = 0;
+ }
+ else if (tag || yyvaltag)
+ rv = 0;
+ if (maxoffset > 0)
+ FREE(offsets);
+ if (p == 0 || *p || rv <= 0)
+ return 0;
+ *theptr = p + 1;
+ return rv;
+}
+
#define ARG_CACHE_SIZE 1024
static struct arg_cache
{
arg_cache[i] = NULL;
}
}
-#endif
+#endif /* defined(YYBTYACC) */
static void
advance_to_start(void)
{
int c;
bucket *bp;
- char *s_cptr;
int s_lineno;
#if defined(YYBTYACC)
char *args = NULL;
for (;;)
{
+ char *s_cptr;
+
c = nextc();
if (c != '%')
break;
s_cptr = cptr;
switch (keyword())
{
+ case XCODE:
+ copy_code();
+ break;
+
case MARK:
no_grammar();
}
c = nextc();
- if (!isalpha(c) && c != '_' && c != '.' && c != '_')
+ if (!isalpha(UCH(c)) && c != '_' && c != '.' && c != '_')
syntax_error(lineno, line, cptr);
bp = get_name();
if (goal == 0)
static void
end_rule(void)
{
- int i;
-
if (!last_was_action && plhs[nrules]->tag)
{
if (pitem[nitems - 1])
{
+ int i;
+
for (i = nitems - 1; (i > 0) && pitem[i]; --i)
continue;
if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag)
- default_action_warning();
+ default_action_warning(plhs[nrules]->name);
}
else
- {
- default_action_warning();
- }
+ default_action_warning(plhs[nrules]->name);
}
last_was_action = 0;
bucket *bp, **bpp;
assert(cache);
+ assert(cache_size >= CACHE_SIZE);
sprintf(cache, "$$%d", ++gensym);
bp = make_bucket(cache);
last_symbol->next = bp;
bp->args = 0;
#endif
- nitems = (Value_t) (nitems + 2);
+ nitems = (Value_t)(nitems + 2);
if (nitems > maxitems)
expand_items();
bpp = pitem + nitems - 1;
{
rule = nrules;
insert_arg_cache(code, rule);
+ trialaction = 1; /* arg rules always run in trial mode */
fprintf(f, "case %d:\n", rule - 2);
if (!lflag)
fprintf(f, line_format, line_number, input_file_name);
fprintf(f, "%s;\n", code);
fprintf(f, "break;\n");
insert_empty_rule();
- plhs[rule]->tag = tag;
+ plhs[rule]->tag = cache_tag(tag, strlen(tag));
plhs[rule]->class = ARGUMENT;
}
else
}
else if (bp->args != argslen)
wrong_number_args_warning("", bp->name);
- if (bp->args > 0 && argslen > 0)
+ if (args != 0)
{
- char *ap;
- int i;
- for (ap = args, i = 0; i < argslen; i++)
+ char *ap = args;
+ int i = 0;
+ int elide_cnt = can_elide_arg(&ap, bp->argtags[0]);
+
+ if (elide_cnt > argslen)
+ elide_cnt = 0;
+ if (elide_cnt)
+ {
+ for (i = 1; i < elide_cnt; i++)
+ if (can_elide_arg(&ap, bp->argtags[i]) != elide_cnt - i)
+ {
+ elide_cnt = 0;
+ break;
+ }
+ }
+ if (elide_cnt)
+ {
+ assert(i == elide_cnt);
+ }
+ else
+ {
+ ap = args;
+ i = 0;
+ }
+ for (; i < argslen; i++)
ap = insert_arg_rule(ap, bp->argtags[i]);
free(args);
}
int i, j, n;
int depth;
#if defined(YYBTYACC)
- int trialaction = 0;
int haveyyval = 0;
#endif
char *tag;
FILE *f = action_file;
- int a_lineno = lineno;
- char *a_line = dup_line();
- char *a_cptr = a_line + (cptr - line);
+ struct ainfo a;
Value_t *offsets = NULL, maxoffset;
bucket **rhs;
+ a.a_lineno = lineno;
+ a.a_line = dup_line();
+ a.a_cptr = a.a_line + (cptr - line);
+
if (last_was_action)
insert_empty_rule();
last_was_action = 1;
+#if defined(YYBTYACC)
+ trialaction = (*cptr == L_BRAC);
+#endif
fprintf(f, "case %d:\n", nrules - 2);
#if defined(YYBTYACC)
if (backtrack)
{
- if (*cptr != L_BRAC)
+ if (!trialaction)
fprintf(f, " if (!yytrial)\n");
- else
- trialaction = 1;
}
#endif
if (!lflag)
{
if (pitem[i]->class != ARGUMENT)
{
- offsets[++j] = (Value_t) (i - nitems + 1);
+ offsets[++j] = (Value_t)(i - nitems + 1);
}
}
}
FREE(d_line);
goto loop;
}
- else if (isdigit(c))
+ else if (isdigit(UCH(c)))
{
i = get_number();
if (i == 0)
goto loop;
}
#if defined(YYBTYACC)
- else if (isalpha(c) || c == '_')
+ else if (isalpha(UCH(c)) || c == '_')
{
char *arg = scan_id();
for (i = plhs[nrules]->args - 1; i >= 0; i--)
break;
if (i < 0)
unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr);
- fprintf(f, "yystack.l_mark[%d].%s", i - plhs[nrules]->args +
- 1 - n, tag);
+ fprintf(f, "yystack.l_mark[%d].%s",
+ i - plhs[nrules]->args + 1 - n, tag);
FREE(d_line);
goto loop;
}
goto loop;
}
#if defined(YYBTYACC)
- else if (isalpha(cptr[1]) || cptr[1] == '_')
+ else if (isalpha(UCH(cptr[1])) || cptr[1] == '_')
{
char *arg;
++cptr;
fprintf(f, "yystack.p_mark[%d]", offsets[i]);
goto loop;
}
+ else if (cptr[1] == '-')
+ {
+ cptr += 2;
+ i = get_number();
+ fprintf(f, "yystack.p_mark[%d]", -i - n);
+ goto loop;
+ }
}
#endif
- if (isalpha(c) || c == '_' || c == '$')
+ if (IS_NAME1(c))
{
do
{
putc(c, f);
c = *++cptr;
}
- while (isalnum(c) || c == '_' || c == '$');
+ while (IS_NAME2(c));
goto loop;
}
++cptr;
goto loop;
}
fprintf(f, "\nbreak;\n");
- FREE(a_line);
+ FREE(a.a_line);
if (maxoffset > 0)
FREE(offsets);
return;
get_line();
if (line)
goto loop;
- unterminated_action(a_lineno, a_line, a_cptr);
+ unterminated_action(&a);
case ';':
if (depth > 0)
goto loop;
fprintf(f, "\nbreak;\n");
- free(a_line);
+ free(a.a_line);
if (maxoffset > 0)
FREE(offsets);
return;
}
#endif
fprintf(f, "\nbreak;\n");
- free(a_line);
+ free(a.a_line);
if (maxoffset > 0)
FREE(offsets);
return;
}
#if defined(YYBTYACC)
-static void
-copy_destructor(void)
+static char *
+get_code(struct ainfo *a, const char *loc)
{
int c;
int depth;
char *tag;
- bucket *bp;
- struct mstring *destructor_text = msnew();
- char *code_text;
- int a_lineno;
- char *a_line;
- char *a_cptr;
+ struct mstring *code_mstr = msnew();
if (!lflag)
- msprintf(destructor_text, line_format, lineno, input_file_name);
+ msprintf(code_mstr, line_format, lineno, input_file_name);
cptr = after_blanks(cptr);
if (*cptr == L_CURL)
/* avoid putting curly-braces in first column, to ease editing */
- mputc(destructor_text, '\t');
+ mputc(code_mstr, '\t');
else
syntax_error(lineno, line, cptr);
- a_lineno = lineno;
- a_line = dup_line();
- a_cptr = a_line + (cptr - line);
+ a->a_lineno = lineno;
+ a->a_line = dup_line();
+ a->a_cptr = a->a_line + (cptr - line);
depth = 0;
loop:
c = *cptr;
if (c == '$')
{
- msprintf(destructor_text, "(*val).%s", tag);
+ msprintf(code_mstr, "(*val).%s", tag);
++cptr;
FREE(d_line);
goto loop;
else if (cptr[1] == '$')
{
/* process '$$' later; replacement is context dependent */
- msprintf(destructor_text, "$$");
+ msprintf(code_mstr, "$$");
cptr += 2;
goto loop;
}
char *l_cptr = l_line + (cptr - line);
syntax_error(l_lineno, l_line, l_cptr);
}
- msprintf(destructor_text, "(*loc)");
+ msprintf(code_mstr, "%s", loc);
cptr += 2;
goto loop;
}
- if (isalpha(c) || c == '_' || c == '$')
+ if (IS_NAME1(c))
{
do
{
- mputc(destructor_text, c);
+ mputc(code_mstr, c);
c = *++cptr;
}
- while (isalnum(c) || c == '_' || c == '$');
+ while (IS_NAME2(c));
goto loop;
}
++cptr;
- mputc(destructor_text, c);
+ mputc(code_mstr, c);
switch (c)
{
case '\n':
get_line();
if (line)
goto loop;
- unterminated_action(a_lineno, a_line, a_cptr);
+ unterminated_action(a);
case L_CURL:
++depth;
case R_CURL:
if (--depth > 0)
goto loop;
- goto process_symbols;
+ goto out;
case '\'':
case '"':
{
char *s = copy_string(c);
- msprintf(destructor_text, "%s", s);
+ msprintf(code_mstr, "%s", s);
free(s);
}
goto loop;
case '/':
{
char *s = copy_comment();
- msprintf(destructor_text, "%s", s);
+ msprintf(code_mstr, "%s", s);
free(s);
}
goto loop;
default:
goto loop;
}
- process_symbols:
- code_text = msdone(destructor_text);
+ out:
+ return msdone(code_mstr);
+}
+
+static void
+copy_initial_action(void)
+{
+ struct ainfo a;
+
+ initial_action = get_code(&a, "yyloc");
+ free(a.a_line);
+}
+
+static void
+copy_destructor(void)
+{
+ char *code_text;
+ struct ainfo a;
+ bucket *bp;
+
+ code_text = get_code(&a, "(*loc)");
+
for (;;)
{
- c = nextc();
+ int c = nextc();
if (c == EOF)
unexpected_EOF();
if (c == '<')
default_destructor[UNTYPED_DEFAULT] = bp;
}
if (bp->destructor != NULL)
- destructor_redeclared_warning(a_lineno, a_line, a_cptr);
+ destructor_redeclared_warning(&a);
else
/* replace "$$" with "(*val)" in destructor code */
bp->destructor = process_destructor_XX(code_text, NULL);
default_destructor[TYPED_DEFAULT] = bp;
}
if (bp->destructor != NULL)
- destructor_redeclared_warning(a_lineno, a_line, a_cptr);
+ destructor_redeclared_warning(&a);
else
{
/* postpone re-processing destructor $$s until end of grammar spec */
}
else
{ /* "semantic type" default destructor */
- tag = get_tag();
+ char *tag = get_tag();
bp = lookup_type_destructor(tag);
if (bp->destructor != NULL)
- destructor_redeclared_warning(a_lineno, a_line, a_cptr);
+ destructor_redeclared_warning(&a);
else
/* replace "$$" with "(*val).tag" in destructor code */
bp->destructor = process_destructor_XX(code_text, tag);
}
}
- else if (isalpha(c) || c == '_' || c == '.' || c == '$')
+ else if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
{ /* "symbol" destructor */
bp = get_name();
if (bp->destructor != NULL)
- destructor_redeclared_warning(a_lineno, a_line, a_cptr);
+ destructor_redeclared_warning(&a);
else
{
/* postpone re-processing destructor $$s until end of grammar spec */
else
break;
}
- free(a_line);
+ free(a.a_line);
free(code_text);
}
msprintf(new_code, "(*val).%s", tag);
goto loop;
}
- if (isalpha(c) || c == '_' || c == '$')
+ if (IS_NAME1(c))
{
do
{
mputc(new_code, c);
c = *++codeptr;
}
- while (isalnum(c) || c == '_' || c == '$');
+ while (IS_NAME2(c));
goto loop;
}
++codeptr;
syntax_error(lineno, line, cptr);
c = nextc();
- if (isalpha(c) || c == '_' || c == '.' || c == '$')
+ if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
bp = get_name();
else if (c == '\'' || c == '"')
bp = get_literal();
else
{
syntax_error(lineno, line, cptr);
+ /*NOTREACHED */
}
if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
static void
read_grammar(void)
{
- int c;
-
initialize_grammar();
advance_to_start();
for (;;)
{
- c = nextc();
+ int c = nextc();
+
if (c == EOF)
break;
- if (isalpha(c)
+ if (isalpha(UCH(c))
|| c == '_'
|| c == '.'
|| c == '$'
pack_names(void)
{
bucket *bp;
- char *p, *s, *t;
+ char *p;
+ char *t;
name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
for (bp = first_symbol; bp; bp = bp->next)
t = name_pool + 13;
for (bp = first_symbol; bp; bp = bp->next)
{
+ char *s = bp->name;
+
p = t;
- s = bp->name;
while ((*t++ = *s++) != 0)
continue;
FREE(bp->name);
static void
protect_string(char *src, char **des)
{
- unsigned len;
- char *s;
- char *d;
-
*des = src;
if (src)
{
- len = 1;
+ char *s;
+ char *d;
+
+ unsigned len = 1;
+
s = src;
while (*s)
{
if (bp->class == TERM)
++ntokens;
}
- start_symbol = (Value_t) ntokens;
- nvars = (Value_t) (nsyms - ntokens);
+ start_symbol = (Value_t)ntokens;
+ nvars = (Value_t)(nsyms - ntokens);
symbol_name = TMALLOC(char *, nsyms);
NO_SPACE(symbol_name);
v[start_symbol] = 0;
i = 1;
- j = (Value_t) (start_symbol + 1);
+ j = (Value_t)(start_symbol + 1);
for (bp = first_symbol; bp; bp = bp->next)
{
if (bp->class == TERM)
for (i = 1; i < ntokens; ++i)
v[i]->index = i;
- goal->index = (Index_t) (start_symbol + 1);
- k = (Value_t) (start_symbol + 2);
+ goal->index = (Index_t)(start_symbol + 1);
+ k = (Value_t)(start_symbol + 2);
while (++i < nsyms)
if (v[i] != goal)
{
goal->value = 0;
k = 1;
- for (i = (Value_t) (start_symbol + 1); i < nsyms; ++i)
+ for (i = (Value_t)(start_symbol + 1); i < nsyms; ++i)
{
if (v[i] != goal)
{
symbol_prec[start_symbol] = 0;
symbol_assoc[start_symbol] = TOKEN;
#if defined(YYBTYACC)
- symbol_pval[start_symbol] = (Value_t) (max_tok_pval + 1);
+ symbol_pval[start_symbol] = (Value_t)(max_tok_pval + 1);
#endif
for (++i; i < nsyms; ++i)
{
symbol_prec[k] = v[i]->prec;
symbol_assoc[k] = v[i]->assoc;
#if defined(YYBTYACC)
- symbol_pval[k] = (Value_t) ((max_tok_pval + 1) + v[i]->value + 1);
+ symbol_pval[k] = (Value_t)((max_tok_pval + 1) + v[i]->value + 1);
if (destructor)
{
symbol_destructor[k] = v[i]->destructor;
{
int i;
Value_t j;
- Assoc_t assoc;
- Value_t prec2;
ritem = TMALLOC(Value_t, nitems);
NO_SPACE(ritem);
j = 4;
for (i = 3; i < nrules; ++i)
{
+ Assoc_t assoc;
+ Value_t prec2;
+
#if defined(YYBTYACC)
if (plhs[i]->args > 0)
{
}
++j;
}
- ritem[j] = (Value_t) - i;
+ ritem[j] = (Value_t)-i;
++j;
if (rprec[i] == UNDEFINED)
{
{
int i;
bucket *bp;
- char *tag;
for (i = 2; i < nsyms; ++i)
{
- tag = symbol_type_tag[i];
+ char *tag = symbol_type_tag[i];
+
if (symbol_destructor[i] == NULL)
{
if (tag == NULL)
#ifdef NO_LEAKS
static param *
-free_declarations(param * list)
+free_declarations(param *list)
{
while (list != 0)
{