From 3d2eca34ff383dff1f070e85115ce7bd816999a0 Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Tue, 22 May 2012 13:01:39 -0300 Subject: [PATCH] b2/: meta-variable $ for "previously matched variable" We need this for iterative processing of FN. --- b2/SUBST | 5 ++++- b2/boom.c | 1 + b2/lang.h | 2 ++ b2/lang.y | 16 +++++++++++++++- b2/param.h | 2 ++ b2/subex.c | 39 ++++++++++++++++++++++++--------------- b2/subst.c | 4 ++++ 7 files changed, 52 insertions(+), 17 deletions(-) diff --git a/b2/SUBST b/b2/SUBST index 595a855..92d3253 100644 --- a/b2/SUBST +++ b/b2/SUBST @@ -1,5 +1,7 @@ FN=DNP { ignore } +FN=X(*) { $=$1 } + REF=R[0-9]* { T=R VAL=(#R) { R=$1 } @@ -23,8 +25,9 @@ variable: $foo, ... with curly braces: ${foo}, ... -input variable: +input variable (in pattern): $$ +the input variable ($) can also be used as LHS for matches and assignments Caveat: diff --git a/b2/boom.c b/b2/boom.c index 55d7a2e..0a1cde8 100644 --- a/b2/boom.c +++ b/b2/boom.c @@ -94,6 +94,7 @@ int main(int argc, char **argv) void (*process)(const char *name) = parse_hierarchy; int i; + dollar = unique("$"); for (i = 1; i != argc; i++) { if (*argv[i] == '-') { if (!strcmp(argv[i], "-c")) diff --git a/b2/lang.h b/b2/lang.h index c5c2c2a..00ac8eb 100644 --- a/b2/lang.h +++ b/b2/lang.h @@ -17,6 +17,8 @@ #include "subst.h" +extern const char *dollar; /* "$" */ + extern struct action hierarchy; extern struct subst *substitutions; diff --git a/b2/lang.y b/b2/lang.y index 64d5ee4..ce14400 100644 --- a/b2/lang.y +++ b/b2/lang.y @@ -25,6 +25,8 @@ #include "y.tab.h" +const char *dollar; + struct action hierarchy; struct subst *substitutions = NULL; @@ -110,6 +112,7 @@ static const struct field *top_field(void) %type stock %type providers provider %type substitutions block opt_block +%type word_or_dollar %% @@ -589,7 +592,7 @@ block: { $$ = NULL; } - | WORD relop PATTERN opt_block block + | word_or_dollar relop PATTERN opt_block block { if ($4) { if ($2 != rel_eq) @@ -622,6 +625,17 @@ block: } ; +word_or_dollar: + '$' + { + $$ = dollar; + } + | WORD + { + $$ = $1; + } + ; + opt_block: { $$ = NULL; diff --git a/b2/param.h b/b2/param.h index 09561d8..49ee927 100644 --- a/b2/param.h +++ b/b2/param.h @@ -66,6 +66,8 @@ struct value { * When using "struct param" to store (string) variables not associated to a * field, then u.name contains the variable name, "op" contains the relational * operator (default rel_eq), and value.u.s contains the variable's value. + * + * If the variable is "$", then u.name is set to NULL. */ struct param { diff --git a/b2/subex.c b/b2/subex.c index fe058d0..9ee6479 100644 --- a/b2/subex.c +++ b/b2/subex.c @@ -20,6 +20,7 @@ #include "util.h" #include "vstring.h" +#include "lang.h" #include "relop.h" #include "subst.h" #include "subex.h" @@ -163,46 +164,53 @@ static int do_match_1(const char *var, const regex_t *re, } -static int do_match(const char *var, const regex_t *re, +static int do_match(const char **var, const regex_t *re, const struct param *in, const struct param *out, const char **val, regmatch_t *match) { int i; - if (var != fn) - return do_match_1(var, re, in, out, val, match); + if (*var != fn) + return do_match_1(*var, re, in, out, val, match); for (i = 0; i != FIELDS; i++) - if (!do_match_1(f[i], re, in, out, val, match)) + if (!do_match_1(f[i], re, in, out, val, match)) { + *var = f[i]; return 0; + } return -1; } static const struct subst *recurse_sub(const struct subst *sub, - const struct param *in, const char *s, const regmatch_t *match, - const char *units, struct param **out) + const struct param *in, const char *matched_var, const char *matched_val, + const regmatch_t *match, const char *units, struct param **out) { const struct subst *jump; regmatch_t m_tmp[10]; - const char *val; + const char *var, *val; char *tmp; while (sub) { switch (sub->type) { case st_match: - if (do_match(sub->u.match.src, &sub->u.match.re, + var = sub->u.match.src; + if (var == dollar) + var = matched_var; + if (do_match(&var, &sub->u.match.re, in, *out, &val, m_tmp)) break; - jump = recurse_sub(sub->u.match.block, in, val, m_tmp, - sub->u.match.units, out); + jump = recurse_sub(sub->u.match.block, in, + var, val, m_tmp, sub->u.match.units, out); if (jump && jump != sub) return jump; break; case st_assign: - tmp = compose(sub->u.assign.pat, in, *out, s, match, - units); - do_assign(sub->u.assign.dst, out, sub->u.assign.op, - tmp); + tmp = compose(sub->u.assign.pat, in, *out, matched_val, + match, units); + var = sub->u.assign.dst; + if (var == dollar) + var = matched_var; + do_assign(var, out, sub->u.assign.op, tmp); break; case st_end: return &jump_end; @@ -237,5 +245,6 @@ int substitute(const struct subst *sub, const struct param *in, } } *out = NULL; - return recurse_sub(sub, in, NULL, NULL, NULL, out) != &jump_ignore; + return recurse_sub(sub, in, NULL, NULL, NULL, NULL, out) + != &jump_ignore; } diff --git a/b2/subst.c b/b2/subst.c index e6d0af6..7168ded 100644 --- a/b2/subst.c +++ b/b2/subst.c @@ -356,10 +356,14 @@ static void recurse_fin(struct subst *sub, const struct parent *parent) sub->prev = prev; switch (sub->type) { case st_match: + if (!parent && sub->u.match.src == dollar) + yyerror("$ without match"); next.sub = sub; recurse_fin(sub->u.match.block, &next); break; case st_assign: + if (!parent && sub->u.assign.dst == dollar) + yyerror("$ without match"); check_chunks(sub->u.assign.pat, parent, prev); break; case st_end: