1
0
mirror of git://projects.qi-hardware.com/eda-tools.git synced 2024-11-26 11:19:41 +02:00

b2/: move all error handling from subex to subst

This makes checking of variables more strict: a variable can only
be used in the right -hand side of an assignment if it has been
assigned by an unconditional predecessor or if it has been matched
by a parent.

Things that wouldn't work anymore:

REF=X* {
	FN=*V { X=Y }
	Z=$X	/* we can't be sure X=Y was taken */
}

FN=*R {
	X=$REF	/* no previous use of REF */
}
This commit is contained in:
Werner Almesberger 2012-05-21 00:20:07 -03:00
parent 6fd5313917
commit 3ad6c2c44b
3 changed files with 71 additions and 16 deletions

View File

@ -20,7 +20,6 @@
#include "util.h" #include "util.h"
#include "vstring.h" #include "vstring.h"
#include "lang.h"
#include "relop.h" #include "relop.h"
#include "subst.h" #include "subst.h"
#include "subex.h" #include "subex.h"
@ -106,21 +105,18 @@ static char *compose(const struct chunk *c,
val = var_lookup(in, c->u.var); val = var_lookup(in, c->u.var);
if (!val) if (!val)
val = var_lookup(out, c->u.var); val = var_lookup(out, c->u.var);
if (!val) assert(val);
yyerrorf("unknown variable \"%s\"", c->u.var);
append(&res, &res_len, val); append(&res, &res_len, val);
break; break;
case ct_sub: case ct_sub:
n = c->u.sub; n = c->u.sub;
if (!s) assert(s);
yyerrorf("$%c without prior match",
n ? n+'0' : '$');
if (!n) { if (!n) {
append(&res, &res_len, s); append(&res, &res_len, s);
break; break;
} }
if (match[n-1].rm_so == -1) if (match[n-1].rm_so == -1)
yyerrorf("substring $%d out of range", n); break;
len = match[n-1].rm_eo-match[n-1].rm_so; len = match[n-1].rm_eo-match[n-1].rm_so;
tmp = alloc_size(len); tmp = alloc_size(len);
memcpy(tmp, s+match[n-1].rm_so, len); memcpy(tmp, s+match[n-1].rm_so, len);

View File

@ -110,11 +110,11 @@ struct subst *subst_match(const char *src, const char *re)
char error[1000]; char error[1000];
struct subst *sub; struct subst *sub;
char *tmp; char *tmp;
int parens, err; int err;
sub = alloc_subst(st_match); sub = alloc_subst(st_match);
sub->u.match.src = src; sub->u.match.src = src;
tmp = prepare_re(re, &parens, sub->u.match.units); tmp = prepare_re(re, &sub->u.match.parens, sub->u.match.units);
err = regcomp(&sub->u.match.re, tmp, REG_EXTENDED); err = regcomp(&sub->u.match.re, tmp, REG_EXTENDED);
free(tmp); free(tmp);
if (err) { if (err) {
@ -287,18 +287,74 @@ static const struct subst *resolve_jump(const char *name,
} }
static void recurse_fin(struct subst *sub, const struct parent *parent) static int find_var_use(const char *var, const struct subst *sub)
{ {
struct parent next = {
.sub = sub,
.parent = parent,
};
while (sub) { while (sub) {
switch (sub->type) { switch (sub->type) {
case st_match: case st_match:
recurse_fin(sub->u.match.block, &next); if (sub->u.match.src == var)
return 1;
break;
case st_assign: case st_assign:
if (sub->u.assign.dst == var)
return 1;
break;
default:
break;
}
sub = sub->prev;
}
return 0;
}
static void check_chunks(const struct chunk *c, const struct parent *parent,
const struct subst *prev)
{
int parens;
while (c) {
switch (c->type) {
case ct_sub:
if (!parent)
yyerrorf("$%c without match",
c->u.sub ? c->u.sub+'0' : '$');
parens = parent->sub->u.match.parens;
if (c->u.sub > parens)
yyerrorf("$%d but only %d parenthes%s",
c->u.sub, parens,
parens == 1 ? "is" : "es");
break;
case ct_var:
if (!find_var_use(c->u.var, prev))
yyerrorf("$%s may be undefined", c->u.var);
break;
default:
break;
}
c = c->next;
}
}
static void recurse_fin(struct subst *sub, const struct parent *parent)
{
struct parent next = {
.parent = parent,
};
const struct subst *prev;
prev = parent ? parent->sub : NULL;
while (sub) {
sub->prev = prev;
switch (sub->type) {
case st_match:
next.sub = sub;
recurse_fin(sub->u.match.block, &next);
break;
case st_assign:
check_chunks(sub->u.assign.pat, parent, prev);
break;
case st_end: case st_end:
break; break;
case st_break: case st_break:
@ -308,6 +364,7 @@ static void recurse_fin(struct subst *sub, const struct parent *parent)
default: default:
abort(); abort();
} }
prev = sub;
sub = sub->next; sub = sub->next;
} }
} }

View File

@ -52,6 +52,7 @@ struct subst {
regex_t re; regex_t re;
struct subst *block; struct subst *block;
char units[10]; char units[10];
int parens; /* number of parentheses */
} match; } match;
struct { struct {
const char *dst; const char *dst;
@ -61,6 +62,7 @@ struct subst {
const struct subst *jump; const struct subst *jump;
const char *tmp; /* jump target name; for subst_finalize */ const char *tmp; /* jump target name; for subst_finalize */
} u; } u;
const struct subst *prev; /* for tracking availability of variables */
struct subst *next; struct subst *next;
}; };