mirror of
git://projects.qi-hardware.com/eda-tools.git
synced 2025-04-21 12:27:27 +03:00
b2/: finish unit handling and move most of its processing to the match side
The ${foo#unit} syntax didn't really make sense because it created
a large number of potential error conditions on the assignment side
and didn't help with finding compatible fields.
With all this moved to the match side, an invalid syntax simply causes
a mismatch.
This commit is contained in:
72
b2/subst.c
72
b2/subst.c
@@ -38,11 +38,33 @@ static struct subst *alloc_subst(enum subst_type type)
|
||||
}
|
||||
|
||||
|
||||
static char *prepare_re(const char *re)
|
||||
/*
|
||||
* With M the SI multiplier prefixes and U the unit character, our regexp
|
||||
* is
|
||||
*
|
||||
* (-?[0-9]+\.?[[0-9]*M?U?|-?[0-9]+[UM][0-9]*)
|
||||
*
|
||||
* The first part is for things like 10, 1.2k, 3.3V, -2mA, etc.
|
||||
* The second part is for things like 1k20, 1R2, etc.
|
||||
*/
|
||||
|
||||
static void unit_expr(char **res, int *res_len, char unit)
|
||||
{
|
||||
append(res, res_len, "(-?[0-9]+\\.?[0-9]*[" MULT_CHARS "]?");
|
||||
append_char(res, res_len, unit);
|
||||
append(res, res_len, "?|-?[0-9]+[");
|
||||
append_char(res, res_len, unit);
|
||||
append(res, res_len, MULT_CHARS "][0-9]*)");
|
||||
}
|
||||
|
||||
|
||||
static char *prepare_re(const char *re, int *parens, char *units)
|
||||
{
|
||||
char *res = NULL;
|
||||
int res_len = 0;
|
||||
|
||||
*parens = 0;
|
||||
memset(units, 0, 10);
|
||||
append_char(&res, &res_len, '^');
|
||||
while (*re) {
|
||||
switch (*re) {
|
||||
@@ -61,6 +83,16 @@ static char *prepare_re(const char *re)
|
||||
append_n(&res, &res_len, re, 2);
|
||||
re++;
|
||||
break;
|
||||
case '(':
|
||||
(*parens)++;
|
||||
if (re[1] == '#' && re[2] && isalpha(re[2]) &&
|
||||
re[3] == ')') {
|
||||
units[*parens-1] = re[2];
|
||||
unit_expr(&res, &res_len, re[2]);
|
||||
re += 3;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
append_char(&res, &res_len, *re);
|
||||
}
|
||||
@@ -77,11 +109,11 @@ struct subst *subst_match(const char *src, const char *re)
|
||||
char error[1000];
|
||||
struct subst *sub;
|
||||
char *tmp;
|
||||
int err;
|
||||
int parens, err;
|
||||
|
||||
sub = alloc_subst(st_match);
|
||||
sub->u.match.src = src;
|
||||
tmp = prepare_re(re);
|
||||
tmp = prepare_re(re, &parens, sub->u.match.units);
|
||||
err = regcomp(&sub->u.match.re, tmp, REG_EXTENDED);
|
||||
free(tmp);
|
||||
if (err) {
|
||||
@@ -102,7 +134,6 @@ static void end_chunk(struct chunk ***last, const char *start, const char *s)
|
||||
c = alloc_type(struct chunk);
|
||||
c->type = ct_string;
|
||||
c->u.s = stralloc_n(start, s-start);;
|
||||
c->unit = NULL;
|
||||
c->next = NULL;
|
||||
**last = c;
|
||||
*last = &c->next;
|
||||
@@ -154,28 +185,9 @@ static const char *parse_var(struct chunk *c, const char *s)
|
||||
c->u.sub = 0;
|
||||
}
|
||||
|
||||
if (*t != '#') {
|
||||
if (braced) {
|
||||
assert(*t == '}');
|
||||
t++;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
s = ++t;
|
||||
while (*t) {
|
||||
if (braced && *t == '}')
|
||||
break;
|
||||
if (!braced && t != s)
|
||||
break;
|
||||
t++;
|
||||
}
|
||||
if (s == t)
|
||||
yyerror("invalid unit");
|
||||
c->unit = stralloc_n(s, t-s);
|
||||
if (braced) {
|
||||
if (!*t)
|
||||
yyerror("unterminated unit");
|
||||
if (*t != '}')
|
||||
yyerror("invalid variable name");
|
||||
t++;
|
||||
}
|
||||
return t;
|
||||
@@ -204,7 +216,6 @@ static struct chunk *parse_pattern(const char *s)
|
||||
|
||||
end_chunk(&last, start, s);
|
||||
c = alloc_type(struct chunk);
|
||||
c->unit = NULL;
|
||||
c->next = NULL;
|
||||
*last = c;
|
||||
last = &c->next;
|
||||
@@ -324,18 +335,13 @@ static void dump_chunks(FILE *file, const struct chunk *c)
|
||||
break;
|
||||
case ct_sub:
|
||||
if (c->u.sub)
|
||||
fprintf(file, "${%d", c->u.sub);
|
||||
fprintf(file, "$%d", c->u.sub);
|
||||
else
|
||||
fprintf(file, "${$");
|
||||
fprintf(file, "$$");
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
if (c->type != ct_string) {
|
||||
if (c->unit)
|
||||
fprintf(file, "#%s", c->unit);
|
||||
fprintf(file, "}");
|
||||
}
|
||||
c = c->next;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user