Date:2012-05-21 02:55:54 (11 years 10 months ago)
Author:Werner Almesberger
Commit:99e577744871520707c37cfc4e6fe5d491ab7dcc
Message: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.
Files: b2/SUBST (2 diffs)
b2/subex.c (6 diffs)
b2/subst.c (7 diffs)
b2/subst.h (3 diffs)

Change Details

b2/SUBST
11REF=R[0-9]* {
22    T=R
3    VAL=* { R=$$#R }
3    VAL=(#R) { R=$1 }
44    TOL = 5%
5    FN=*% { TOL=${$#%} }
5    FN=*% { TOL=$$ }
66    break REF
77// end break again
88}
99
1010/*
11pattern: () * ? .
11pattern:
12  () | like in RE
13  * ? like in glob
14  (#U) expect a numeric value of unit U (use substring to get canonical value)
15
1216subst: $1 ... $field
1317
1418substring:
...... 
1721  $foo, ...
1822with curly braces:
1923  ${foo}, ...
20unit conversion:
21  $foo#V
22  ${1#R}
2324input variable:
2425  $$
26
27  Caveat:
28
29  Wrong: FN=* { X=$FN } there is no variable called FN
30  Right: FN=* { X=$$ } yields the Fn field selected by FN
31
32  Wrong: VAL=(#R) { R=$VAL } yields literal value
33  Wrong: VAL=(#R) { R=$$ } yields literal value
34  Right: VAL=(#R) { R=$1 } yield canonicalized value
2535*/
b2/subex.c
1313#include <stdlib.h>
1414#include <stdio.h>
1515#include <string.h>
16#include <ctype.h>
1617#include <sys/types.h>
1718#include <regex.h>
19#include <assert.h>
1820
1921#include "util.h"
2022#include "vstring.h"
...... 
3234static struct subst jump_end;
3335
3436
35/*
36 * TODO: decide what to do with units
37 */
37
38static char *canonicalize(const char *s, char unit)
39{
40    char *res;
41    int res_len = 0;
42    int seen_dot = 0;
43    int seen_unit = 0;
44    char mult = 0;
45
46    if (!unit)
47        return stralloc(s);
48    res = stralloc("");
49    while (*s) {
50        if (*s == unit) {
51            assert(!seen_unit);
52            if (!s[1])
53                break;
54            if (!seen_dot)
55                append_char(&res, &res_len, '.');
56            seen_unit = seen_dot = 1;
57            s++;
58            continue;
59        }
60        if (*s == '.') {
61            assert(!seen_dot);
62            append_char(&res, &res_len, '.');
63            seen_dot = 1;
64        } else if (*s == '-' || isdigit(*s)) {
65            append_char(&res, &res_len, *s);
66            s++;
67            continue;
68        } else if (strchr(MULT_CHARS, *s)) {
69            assert(!seen_unit);
70            assert(!mult);
71            mult = *s;
72            if (!seen_dot)
73                append_char(&res, &res_len, '.');
74            seen_dot = 1;
75        } else {
76            abort();
77        }
78        s++;
79    }
80    if (res_len && res[res_len-1] == '.')
81        res_len--;
82    if (mult)
83        append_char(&res, &res_len, mult);
84    append_char(&res, &res_len, unit);
85    return res;
86}
87
3888
3989static char *compose(const struct chunk *c,
4090    const struct var *in, const struct var *out,
41    const char *s, const regmatch_t *match)
91    const char *s, const regmatch_t *match, const char *units)
4292{
4393    char *res = stralloc("");
44    int res_len = 0;
94    int res_len = 0, len;
4595    const char *val;
96    char *tmp, *tmp2;
4697    int n;
4798
4899    while (c) {
...... 
69120            }
70121            if (match[n-1].rm_so == -1)
71122                yyerrorf("substring $%d out of range", n);
72#if 0
73            len = match[n-1].rm_eo-match[n-1].rm_so);
123            len = match[n-1].rm_eo-match[n-1].rm_so;
74124            tmp = alloc_size(len);
75125            memcpy(tmp, s+match[n-1].rm_so, len);
76126            tmp[len] = 0;
77            tmp2 = canonicalize(tmp, c->unit);
127            tmp2 = canonicalize(tmp, units ? units[n-1] : 0);
78128            append(&res, &res_len, tmp2);
79#endif
80            append_n(&res, &res_len, s+match[n-1].rm_so,
81                match[n-1].rm_eo-match[n-1].rm_so);
129            free(tmp);
130            free(tmp2);
82131            break;
83132        default:
84133            abort();
...... 
147196
148197static const struct subst *recurse_sub(const struct subst *sub,
149198    const struct var *in, const char *s, const regmatch_t *match,
150    struct var **out)
199    const char *units, struct var **out)
151200{
152201    const struct subst *jump;
153202    regmatch_t m_tmp[10];
...... 
161210                in, *out, &val, m_tmp))
162211                break;
163212            jump = recurse_sub(sub->u.match.block, in, val, m_tmp,
164                out);
213                sub->u.match.units, out);
165214            if (jump && jump != sub)
166215                return jump;
167216            break;
168217        case st_assign:
169            tmp = compose(sub->u.assign.pat, in, *out, s, match);
218            tmp = compose(sub->u.assign.pat, in, *out, s, match,
219                units);
170220            do_assign(sub->u.assign.dst, out, tmp);
171221            break;
172222        case st_end:
...... 
199249            f[i] = unique(tmp);
200250        }
201251    }
202    recurse_sub(sub, in, NULL, NULL, &out);
252    recurse_sub(sub, in, NULL, NULL, NULL, &out);
203253    return out;
204254}
205255
b2/subst.c
3838}
3939
4040
41static char *prepare_re(const char *re)
41/*
42 * With M the SI multiplier prefixes and U the unit character, our regexp
43 * is
44 *
45 * (-?[0-9]+\.?[[0-9]*M?U?|-?[0-9]+[UM][0-9]*)
46 *
47 * The first part is for things like 10, 1.2k, 3.3V, -2mA, etc.
48 * The second part is for things like 1k20, 1R2, etc.
49 */
50
51static void unit_expr(char **res, int *res_len, char unit)
52{
53    append(res, res_len, "(-?[0-9]+\\.?[0-9]*[" MULT_CHARS "]?");
54    append_char(res, res_len, unit);
55    append(res, res_len, "?|-?[0-9]+[");
56    append_char(res, res_len, unit);
57    append(res, res_len, MULT_CHARS "][0-9]*)");
58}
59
60
61static char *prepare_re(const char *re, int *parens, char *units)
4262{
4363    char *res = NULL;
4464    int res_len = 0;
4565
66    *parens = 0;
67    memset(units, 0, 10);
4668    append_char(&res, &res_len, '^');
4769    while (*re) {
4870        switch (*re) {
...... 
6183            append_n(&res, &res_len, re, 2);
6284            re++;
6385            break;
86        case '(':
87            (*parens)++;
88            if (re[1] == '#' && re[2] && isalpha(re[2]) &&
89                re[3] == ')') {
90                units[*parens-1] = re[2];
91                unit_expr(&res, &res_len, re[2]);
92                re += 3;
93                break;
94            }
95            /* fall through */
6496        default:
6597            append_char(&res, &res_len, *re);
6698        }
...... 
77109    char error[1000];
78110    struct subst *sub;
79111    char *tmp;
80    int err;
112    int parens, err;
81113
82114    sub = alloc_subst(st_match);
83115    sub->u.match.src = src;
84    tmp = prepare_re(re);
116    tmp = prepare_re(re, &parens, sub->u.match.units);
85117    err = regcomp(&sub->u.match.re, tmp, REG_EXTENDED);
86118    free(tmp);
87119    if (err) {
...... 
102134    c = alloc_type(struct chunk);
103135    c->type = ct_string;
104136    c->u.s = stralloc_n(start, s-start);;
105    c->unit = NULL;
106137    c->next = NULL;
107138    **last = c;
108139    *last = &c->next;
...... 
154185        c->u.sub = 0;
155186    }
156187
157    if (*t != '#') {
158        if (braced) {
159            assert(*t == '}');
160            t++;
161        }
162        return t;
163    }
164
165    s = ++t;
166    while (*t) {
167        if (braced && *t == '}')
168            break;
169        if (!braced && t != s)
170            break;
171        t++;
172    }
173    if (s == t)
174        yyerror("invalid unit");
175    c->unit = stralloc_n(s, t-s);
176188    if (braced) {
177        if (!*t)
178            yyerror("unterminated unit");
189        if (*t != '}')
190            yyerror("invalid variable name");
179191        t++;
180192    }
181193    return t;
...... 
204216
205217        end_chunk(&last, start, s);
206218        c = alloc_type(struct chunk);
207        c->unit = NULL;
208219        c->next = NULL;
209220        *last = c;
210221        last = &c->next;
...... 
324335            break;
325336        case ct_sub:
326337            if (c->u.sub)
327                fprintf(file, "${%d", c->u.sub);
338                fprintf(file, "$%d", c->u.sub);
328339            else
329                fprintf(file, "${$");
340                fprintf(file, "$$");
330341            break;
331342        default:
332343            abort();
333344        }
334        if (c->type != ct_string) {
335            if (c->unit)
336                fprintf(file, "#%s", c->unit);
337            fprintf(file, "}");
338        }
339345        c = c->next;
340346    }
341347}
b2/subst.h
3131        const char *var;
3232        int sub; /* 0 if $$ */
3333    } u;
34    const char *unit; /* NULL if no conversion specified */
3534    struct chunk *next;
3635};
3736
...... 
5049            const char *src;
5150            regex_t re;
5251            struct subst *block;
52            char units[10];
5353        } match;
5454        struct {
5555            const char *dst;
...... 
6262};
6363
6464
65#define MULT_CHARS "GMkmunpf"
66
67
6568struct subst *subst_match(const char *src, const char *re);
6669struct subst *subst_assign(const char *dst, const char *pat);
6770struct subst *subst_end(void);

Archive Download the corresponding diff file

Branches:
master



interactive