[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

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



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 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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]