1
0
mirror of git://projects.qi-hardware.com/eda-tools.git synced 2024-11-23 05:31:53 +02: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:
Werner Almesberger 2012-05-20 21:55:54 -03:00
parent adecef8d4a
commit 99e5777448
4 changed files with 124 additions and 55 deletions

View File

@ -1,14 +1,18 @@
REF=R[0-9]* { REF=R[0-9]* {
T=R T=R
VAL=* { R=$$#R } VAL=(#R) { R=$1 }
TOL = 5% TOL = 5%
FN=*% { TOL=${$#%} } FN=*% { TOL=$$ }
break REF break REF
// end break again // end break again
} }
/* /*
pattern: () * ? . pattern:
() | like in RE
* ? like in glob
(#U) expect a numeric value of unit U (use substring to get canonical value)
subst: $1 ... $field subst: $1 ... $field
substring: substring:
@ -17,9 +21,15 @@ variable:
$foo, ... $foo, ...
with curly braces: with curly braces:
${foo}, ... ${foo}, ...
unit conversion:
$foo#V
${1#R}
input variable: input variable:
$$ $$
Caveat:
Wrong: FN=* { X=$FN } there is no variable called FN
Right: FN=* { X=$$ } yields the Fn field selected by FN
Wrong: VAL=(#R) { R=$VAL } yields literal value
Wrong: VAL=(#R) { R=$$ } yields literal value
Right: VAL=(#R) { R=$1 } yield canonicalized value
*/ */

View File

@ -13,8 +13,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <ctype.h>
#include <sys/types.h> #include <sys/types.h>
#include <regex.h> #include <regex.h>
#include <assert.h>
#include "util.h" #include "util.h"
#include "vstring.h" #include "vstring.h"
@ -32,17 +34,66 @@ static const char *fn = NULL, *f[FIELDS];
static struct subst jump_end; static struct subst jump_end;
/*
* TODO: decide what to do with units static char *canonicalize(const char *s, char unit)
*/ {
char *res;
int res_len = 0;
int seen_dot = 0;
int seen_unit = 0;
char mult = 0;
if (!unit)
return stralloc(s);
res = stralloc("");
while (*s) {
if (*s == unit) {
assert(!seen_unit);
if (!s[1])
break;
if (!seen_dot)
append_char(&res, &res_len, '.');
seen_unit = seen_dot = 1;
s++;
continue;
}
if (*s == '.') {
assert(!seen_dot);
append_char(&res, &res_len, '.');
seen_dot = 1;
} else if (*s == '-' || isdigit(*s)) {
append_char(&res, &res_len, *s);
s++;
continue;
} else if (strchr(MULT_CHARS, *s)) {
assert(!seen_unit);
assert(!mult);
mult = *s;
if (!seen_dot)
append_char(&res, &res_len, '.');
seen_dot = 1;
} else {
abort();
}
s++;
}
if (res_len && res[res_len-1] == '.')
res_len--;
if (mult)
append_char(&res, &res_len, mult);
append_char(&res, &res_len, unit);
return res;
}
static char *compose(const struct chunk *c, static char *compose(const struct chunk *c,
const struct var *in, const struct var *out, const struct var *in, const struct var *out,
const char *s, const regmatch_t *match) const char *s, const regmatch_t *match, const char *units)
{ {
char *res = stralloc(""); char *res = stralloc("");
int res_len = 0; int res_len = 0, len;
const char *val; const char *val;
char *tmp, *tmp2;
int n; int n;
while (c) { while (c) {
@ -69,16 +120,14 @@ static char *compose(const struct chunk *c,
} }
if (match[n-1].rm_so == -1) if (match[n-1].rm_so == -1)
yyerrorf("substring $%d out of range", n); yyerrorf("substring $%d out of range", n);
#if 0 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);
tmp[len] = 0; tmp[len] = 0;
tmp2 = canonicalize(tmp, c->unit); tmp2 = canonicalize(tmp, units ? units[n-1] : 0);
append(&res, &res_len, tmp2); append(&res, &res_len, tmp2);
#endif free(tmp);
append_n(&res, &res_len, s+match[n-1].rm_so, free(tmp2);
match[n-1].rm_eo-match[n-1].rm_so);
break; break;
default: default:
abort(); abort();
@ -147,7 +196,7 @@ static int do_match(const char *var, const regex_t *re,
static const struct subst *recurse_sub(const struct subst *sub, static const struct subst *recurse_sub(const struct subst *sub,
const struct var *in, const char *s, const regmatch_t *match, const struct var *in, const char *s, const regmatch_t *match,
struct var **out) const char *units, struct var **out)
{ {
const struct subst *jump; const struct subst *jump;
regmatch_t m_tmp[10]; regmatch_t m_tmp[10];
@ -161,12 +210,13 @@ static const struct subst *recurse_sub(const struct subst *sub,
in, *out, &val, m_tmp)) in, *out, &val, m_tmp))
break; break;
jump = recurse_sub(sub->u.match.block, in, val, m_tmp, jump = recurse_sub(sub->u.match.block, in, val, m_tmp,
out); sub->u.match.units, out);
if (jump && jump != sub) if (jump && jump != sub)
return jump; return jump;
break; break;
case st_assign: case st_assign:
tmp = compose(sub->u.assign.pat, in, *out, s, match); tmp = compose(sub->u.assign.pat, in, *out, s, match,
units);
do_assign(sub->u.assign.dst, out, tmp); do_assign(sub->u.assign.dst, out, tmp);
break; break;
case st_end: case st_end:
@ -199,7 +249,7 @@ struct var *substitute(const struct subst *sub, const struct var *in)
f[i] = unique(tmp); f[i] = unique(tmp);
} }
} }
recurse_sub(sub, in, NULL, NULL, &out); recurse_sub(sub, in, NULL, NULL, NULL, &out);
return out; return out;
} }

View File

@ -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; char *res = NULL;
int res_len = 0; int res_len = 0;
*parens = 0;
memset(units, 0, 10);
append_char(&res, &res_len, '^'); append_char(&res, &res_len, '^');
while (*re) { while (*re) {
switch (*re) { switch (*re) {
@ -61,6 +83,16 @@ static char *prepare_re(const char *re)
append_n(&res, &res_len, re, 2); append_n(&res, &res_len, re, 2);
re++; re++;
break; 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: default:
append_char(&res, &res_len, *re); append_char(&res, &res_len, *re);
} }
@ -77,11 +109,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 err; int parens, 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); tmp = prepare_re(re, &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) {
@ -102,7 +134,6 @@ static void end_chunk(struct chunk ***last, const char *start, const char *s)
c = alloc_type(struct chunk); c = alloc_type(struct chunk);
c->type = ct_string; c->type = ct_string;
c->u.s = stralloc_n(start, s-start);; c->u.s = stralloc_n(start, s-start);;
c->unit = NULL;
c->next = NULL; c->next = NULL;
**last = c; **last = c;
*last = &c->next; *last = &c->next;
@ -154,28 +185,9 @@ static const char *parse_var(struct chunk *c, const char *s)
c->u.sub = 0; 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 (braced) {
if (!*t) if (*t != '}')
yyerror("unterminated unit"); yyerror("invalid variable name");
t++; t++;
} }
return t; return t;
@ -204,7 +216,6 @@ static struct chunk *parse_pattern(const char *s)
end_chunk(&last, start, s); end_chunk(&last, start, s);
c = alloc_type(struct chunk); c = alloc_type(struct chunk);
c->unit = NULL;
c->next = NULL; c->next = NULL;
*last = c; *last = c;
last = &c->next; last = &c->next;
@ -324,18 +335,13 @@ static void dump_chunks(FILE *file, const struct chunk *c)
break; break;
case ct_sub: case ct_sub:
if (c->u.sub) if (c->u.sub)
fprintf(file, "${%d", c->u.sub); fprintf(file, "$%d", c->u.sub);
else else
fprintf(file, "${$"); fprintf(file, "$$");
break; break;
default: default:
abort(); abort();
} }
if (c->type != ct_string) {
if (c->unit)
fprintf(file, "#%s", c->unit);
fprintf(file, "}");
}
c = c->next; c = c->next;
} }
} }

View File

@ -31,7 +31,6 @@ struct chunk {
const char *var; const char *var;
int sub; /* 0 if $$ */ int sub; /* 0 if $$ */
} u; } u;
const char *unit; /* NULL if no conversion specified */
struct chunk *next; struct chunk *next;
}; };
@ -50,6 +49,7 @@ struct subst {
const char *src; const char *src;
regex_t re; regex_t re;
struct subst *block; struct subst *block;
char units[10];
} match; } match;
struct { struct {
const char *dst; const char *dst;
@ -62,6 +62,9 @@ struct subst {
}; };
#define MULT_CHARS "GMkmunpf"
struct subst *subst_match(const char *src, const char *re); struct subst *subst_match(const char *src, const char *re);
struct subst *subst_assign(const char *dst, const char *pat); struct subst *subst_assign(const char *dst, const char *pat);
struct subst *subst_end(void); struct subst *subst_end(void);