[augeas-devel] [PATCH] Support multiple number of arguments in functions in pathx.c Implement regexp function with 'i' argument.

Raphaël Pinson raphael.pinson at camptocamp.com
Tue Jul 31 22:21:12 UTC 2012


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 <
raphael.pinson at camptocamp.com> 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/augeas-devel/attachments/20120801/b6d7687a/attachment.htm>


More information about the augeas-devel mailing list