This patch adds support for functions with variable arity and implements a version of regexp() with flags. Currently, only the 'i' flag is supported and makes regexp() case-insensitive.
On Wed, Aug 1, 2012 at 12:19 AM, Raphaël Pinson < [email protected]> wrote: > --- > src/pathx.c | 54 +++++++++++++++++++++++++++++++++++++++++++----------- > 1 file changed, 43 insertions(+), 11 deletions(-) > > diff --git a/src/pathx.c b/src/pathx.c > index c6aa4c4..2908223 100644 > --- a/src/pathx.c > +++ b/src/pathx.c > @@ -199,6 +199,7 @@ struct expr { > char *ident; /* E_VAR */ > struct { /* E_APP */ > const struct func *func; > + unsigned int arity; > struct expr **args; > }; > }; > @@ -283,6 +284,7 @@ static void func_position(struct state *state); > static void func_count(struct state *state); > static void func_label(struct state *state); > static void func_regexp(struct state *state); > +static void func_regexp_flag(struct state *state); > static void func_glob(struct state *state); > static void func_int(struct state *state); > > @@ -290,6 +292,9 @@ static const enum type const arg_types_nodeset[] = { > T_NODESET }; > static const enum type const arg_types_string[] = { T_STRING }; > static const enum type const arg_types_bool[] = { T_BOOLEAN }; > > +static const enum type const arg_types_string_string[] = { T_STRING, > T_STRING }; > +static const enum type const arg_types_nodeset_string[] = { T_STRING, > T_STRING }; > + > static const struct func builtin_funcs[] = { > { .name = "last", .arity = 0, .type = T_NUMBER, .arg_types = NULL, > .impl = func_last }, > @@ -306,6 +311,12 @@ static const struct func builtin_funcs[] = { > { .name = "regexp", .arity = 1, .type = T_REGEXP, > .arg_types = arg_types_nodeset, > .impl = func_regexp }, > + { .name = "regexp", .arity = 2, .type = T_REGEXP, > + .arg_types = arg_types_string_string, > + .impl = func_regexp_flag }, > + { .name = "regexp", .arity = 2, .type = T_REGEXP, > + .arg_types = arg_types_nodeset_string, > + .impl = func_regexp_flag }, > { .name = "glob", .arity = 1, .type = T_REGEXP, > .arg_types = arg_types_string, > .impl = func_glob }, > @@ -689,7 +700,7 @@ static void func_int(struct state *state) { > } > > static struct regexp * > -nodeset_as_regexp(struct info *info, struct nodeset *ns, int glob) { > +nodeset_as_regexp(struct info *info, struct nodeset *ns, int glob, int > nocase) { > struct regexp *result = NULL; > struct regexp **rx = NULL; > int used = 0; > @@ -702,7 +713,7 @@ nodeset_as_regexp(struct info *info, struct nodeset > *ns, int glob) { > if (used == 0) { > /* If the nodeset is empty, make sure we produce a regexp > * that never matches anything */ > - result = make_regexp_unescape(info, "[^\001-\7ff]", 0); > + result = make_regexp_unescape(info, "[^\001-\7ff]", nocase); > } else { > if (ALLOC_N(rx, ns->used) < 0) > goto error; > @@ -729,7 +740,7 @@ nodeset_as_regexp(struct info *info, struct nodeset > *ns, int glob) { > return result; > } > > -static void func_regexp_or_glob(struct state *state, int glob) { > +static void func_regexp_or_glob(struct state *state, int glob, int > nocase) { > value_ind_t vind = make_value(T_REGEXP, state); > int r; > > @@ -742,9 +753,9 @@ static void func_regexp_or_glob(struct state *state, > int glob) { > if (glob) > rx = make_regexp_from_glob(state->error->info, v->string); > else > - rx = make_regexp_unescape(state->error->info, v->string, 0); > + rx = make_regexp_unescape(state->error->info, v->string, > nocase); > } else if (v->tag == T_NODESET) { > - rx = nodeset_as_regexp(state->error->info, v->nodeset, glob); > + rx = nodeset_as_regexp(state->error->info, v->nodeset, glob, > nocase); > } else { > assert(0); > } > @@ -767,11 +778,21 @@ static void func_regexp_or_glob(struct state *state, > int glob) { > } > > static void func_regexp(struct state *state) { > - func_regexp_or_glob(state, 0); > + func_regexp_or_glob(state, 0, 0); > +} > + > +static void func_regexp_flag(struct state *state) { > + int nocase = 0; > + struct value *f = pop_value(state); > + > + if (STREQ("i", f->string)) > + nocase = 1; > + > + func_regexp_or_glob(state, 0, nocase); > } > > static void func_glob(struct state *state) { > - func_regexp_or_glob(state, 1); > + func_regexp_or_glob(state, 1, 0); > } > > static bool coerce_to_bool(struct value *v) { > @@ -1345,7 +1366,8 @@ static void check_app(struct expr *expr, struct > state *state) { > int f; > for (f=0; f < ARRAY_CARDINALITY(builtin_funcs); f++) { > const struct func *fn = builtin_funcs + f; > - if (STRNEQ(expr->func->name, fn->name)) > + if (STRNEQ(expr->func->name, fn->name) || > + expr->arity != fn->arity) > continue; > > int match = 1; > @@ -1921,12 +1943,14 @@ static void parse_function_call(struct state > *state) { > const struct func *func = NULL; > struct expr *expr = NULL; > int nargs = 0; > + const char *func_name = NULL; > > for (int i=0; i < ARRAY_CARDINALITY(builtin_funcs); i++) { > if (looking_at(state, builtin_funcs[i].name, "(")) > - func = builtin_funcs + i; > + func_name = builtin_funcs[i].name; > } > - if (func == NULL) { > + > + if (func_name == NULL) { > STATE_ERROR(state, PATHX_ENAME); > return; > } > @@ -1944,7 +1968,14 @@ static void parse_function_call(struct state > *state) { > } > } > > - if (nargs != func->arity) { > + for (int i=0; i < ARRAY_CARDINALITY(builtin_funcs); i++) { > + if (STREQ(func_name, builtin_funcs[i].name) > + && nargs == builtin_funcs[i].arity) { > + func = builtin_funcs + i; > + } > + } > + > + if (func == NULL) { > STATE_ERROR(state, PATHX_EARITY); > return; > } > @@ -1960,6 +1991,7 @@ static void parse_function_call(struct state *state) > { > return; > } > expr->func = func; > + expr->arity = nargs; > for (int i = nargs - 1; i >= 0; i--) > expr->args[i] = pop_expr(state); > > -- > 1.7.9.5 > > -- Raphaël Pinson Administrateur Systèmes & Réseaux Camptocamp France Savoie Technolac BP 352 48, avenue du Lac du Bourget 73372 Le Bourget du Lac, Cedex www.camptocamp.com
_______________________________________________ augeas-devel mailing list [email protected] https://www.redhat.com/mailman/listinfo/augeas-devel
