mirror of
git://projects.qi-hardware.com/eda-tools.git
synced 2024-11-26 11:31:54 +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:
parent
6fd5313917
commit
3ad6c2c44b
10
b2/subex.c
10
b2/subex.c
@ -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);
|
||||||
|
75
b2/subst.c
75
b2/subst.c
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user