[augeas-devel] [PATCH] Add support for an 'i' flag in regexp builtin function

Raphaël Pinson raphael.pinson at camptocamp.com
Wed Aug 1 21:53:38 UTC 2012


This is a new version of the 3rd patch.

As suggested, I added a test against nodesets (test regexp6),
but it fails for a reason I cannot comprehend. It seems that
when two arguments are passed, the nodeset is not properly
parsed, resulting in an empty nodeset, even though the path is
strictly the same as test regexp3 which doesn't fail. 

---
 src/internal.h     |    3 ++-
 src/pathx.c        |   39 +++++++++++++++++++++++++++++----------
 tests/test-xpath.c |   18 ++++++++++++++++++
 tests/xpath.tests  |    7 +++++++
 4 files changed, 56 insertions(+), 11 deletions(-)

diff --git a/src/internal.h b/src/internal.h
index 933722c..1f7bef3 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -503,7 +503,8 @@ typedef enum {
     PATHX_ENOMATCH,
     PATHX_EARITY,
     PATHX_EREGEXP,
-    PATHX_EMMATCH
+    PATHX_EMMATCH,
+    PATHX_EREGEXPFLAG
 } pathx_errcode_t;
 
 struct pathx;
diff --git a/src/pathx.c b/src/pathx.c
index c51f7e4..f4b6e8c 100644
--- a/src/pathx.c
+++ b/src/pathx.c
@@ -49,7 +49,8 @@ static const char *const errcodes[] = {
     "no match for path expression",               /* PATHX_ENOMATCH */
     "wrong number of arguments in function call", /* PATHX_EARITY */
     "invalid regular expression",                 /* PATHX_EREGEXP */
-    "too many matches"                            /* PATHX_EMMATCH */
+    "too many matches",                           /* PATHX_EMMATCH */
+    "wrong flag for regexp"                       /* PATHX_EREGEXPFLAG */
 };
 
 /*
@@ -289,6 +290,8 @@ static void func_int(struct state *state, int nargs);
 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_nodeset_string[] = { T_NODESET, T_STRING };
+static const enum type const arg_types_string_string[] = { T_STRING, T_STRING };
 
 static const struct func builtin_funcs[] = {
     { .name = "last", .arity = 0, .type = T_NUMBER, .arg_types = NULL,
@@ -306,6 +309,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 },
+    { .name = "regexp", .arity = 2, .type = T_REGEXP,
+      .arg_types = arg_types_nodeset_string,
+      .impl = func_regexp },
     { .name = "glob", .arity = 1, .type = T_REGEXP,
       .arg_types = arg_types_string,
       .impl = func_glob },
@@ -701,7 +710,7 @@ static void func_int(struct state *state, int nargs) {
 }
 
 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;
@@ -714,7 +723,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;
@@ -725,7 +734,7 @@ nodeset_as_regexp(struct info *info, struct nodeset *ns, int glob) {
             if (glob)
                 rx[i] = make_regexp_from_glob(info, ns->nodes[i]->value);
             else
-                rx[i] = make_regexp_unescape(info, ns->nodes[i]->value, 0);
+                rx[i] = make_regexp_unescape(info, ns->nodes[i]->value, nocase);
             if (rx[i] == NULL)
                 goto error;
         }
@@ -741,7 +750,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;
 
@@ -754,9 +763,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);
     }
@@ -779,13 +788,23 @@ static void func_regexp_or_glob(struct state *state, int glob) {
 }
 
 static void func_regexp(struct state *state, int nargs) {
-    ensure_arity(1, 1);
-    func_regexp_or_glob(state, 0);
+    int nocase = 0;
+    ensure_arity(1, 2);
+
+    if (nargs == 2) {
+        struct value *f = pop_value(state);
+        if (STREQ("i", f->string))
+            nocase = 1;
+        else
+            STATE_ERROR(state, PATHX_EREGEXPFLAG);
+    }
+
+    func_regexp_or_glob(state, 0, nocase);
 }
 
 static void func_glob(struct state *state, int nargs) {
     ensure_arity(1, 1);
-    func_regexp_or_glob(state, 1);
+    func_regexp_or_glob(state, 1, 0);
 }
 
 static bool coerce_to_bool(struct value *v) {
diff --git a/tests/test-xpath.c b/tests/test-xpath.c
index 313c033..335e7bf 100644
--- a/tests/test-xpath.c
+++ b/tests/test-xpath.c
@@ -316,6 +316,21 @@ static int test_invalid_regexp(struct augeas *aug) {
     return -1;
 }
 
+static int test_wrong_regexp_flag(struct augeas *aug) {
+    int r;
+
+    printf("%-30s ... ", "wrong_regexp_flag");
+    r = aug_match(aug, "/files/*[ * =~ regexp('abc', 'o')]", NULL);
+    if (r >= 0)
+        goto fail;
+
+    printf("PASS\n");
+    return 0;
+ fail:
+    printf("FAIL\n");
+    return -1;
+}
+
 static int run_tests(struct test *tests, int argc, char **argv) {
     char *lensdir;
     struct augeas *aug = NULL;
@@ -356,6 +371,9 @@ static int run_tests(struct test *tests, int argc, char **argv) {
 
         if (test_invalid_regexp(aug) < 0)
             result = EXIT_FAILURE;
+
+        if (test_wrong_regexp_flag(aug) < 0)
+            result = EXIT_FAILURE;
     }
     aug_close(aug);
 
diff --git a/tests/xpath.tests b/tests/xpath.tests
index 742b9ff..d34697f 100644
--- a/tests/xpath.tests
+++ b/tests/xpath.tests
@@ -233,6 +233,13 @@ test regexp3 /files/etc/hosts/*[ipaddr =~ regexp(/files/etc/hosts/*/ipaddr)]
 # Check that we don't crash when the nodeset contains all NULL's
 test regexp4 /files/etc/hosts/*[ipaddr =~ regexp(/files/etc/hosts/*[ipaddr])]
 
+# Check case-insensitive matches
+test regexp5 /files/etc/sysconfig/network-scripts/*[label() =~ regexp('.*-ETH0', 'i')]
+     /files/etc/sysconfig/network-scripts/ifcfg-eth0
+
+test regexp6 /files/etc/hosts/*[ipaddr =~ regexp(/files/etc/hosts/1/ipaddr, 'i')]
+     /files/etc/hosts/1
+
 test glob1 /files[ 'axxa' =~ glob('a*a') ]
      /files
 
-- 
1.7.9.5




More information about the augeas-devel mailing list