[augeas-devel] [PATCH 3/8] path expressions: allow passing a nodeset to function regexp

lutter at redhat.com lutter at redhat.com
Sat May 7 01:12:51 UTC 2011


From: David Lutterkort <lutter at redhat.com>

---
 src/pathx.c       |   68 ++++++++++++++++++++++++++++++++++++++++++-----------
 tests/xpath.tests |    7 +++++
 2 files changed, 61 insertions(+), 14 deletions(-)

diff --git a/src/pathx.c b/src/pathx.c
index a73a83d..a2371f8 100644
--- a/src/pathx.c
+++ b/src/pathx.c
@@ -277,8 +277,8 @@ static void func_count(struct state *state);
 static void func_label(struct state *state);
 static void func_regexp(struct state *state);
 
-static const enum type const count_arg_types[] = { T_NODESET };
-static const enum type const regexp_arg_types[] = { T_STRING };
+static const enum type const arg_types_nodeset[] = { T_NODESET };
+static const enum type const arg_types_string[] = { T_STRING };
 
 static const struct func builtin_funcs[] = {
     { .name = "last", .arity = 0, .type = T_NUMBER, .arg_types = NULL,
@@ -288,11 +288,14 @@ static const struct func builtin_funcs[] = {
     { .name = "label", .arity = 0, .type = T_STRING, .arg_types = NULL,
       .impl = func_label },
     { .name = "count", .arity = 1, .type = T_NUMBER,
-      .arg_types = count_arg_types,
+      .arg_types = arg_types_nodeset,
       .impl = func_count },
     { .name = "regexp", .arity = 1, .type = T_REGEXP,
-      .arg_types = regexp_arg_types,
-      .impl =func_regexp }
+      .arg_types = arg_types_string,
+      .impl = func_regexp },
+    { .name = "regexp", .arity = 1, .type = T_REGEXP,
+      .arg_types = arg_types_nodeset,
+      .impl = func_regexp }
 };
 
 #define CHECK_ERROR                                                     \
@@ -629,28 +632,65 @@ static void func_label(struct state *state) {
     push_value(vind, state);
 }
 
+static struct regexp *
+nodeset_as_regexp(struct info *info, struct nodeset *ns) {
+    struct regexp *result = NULL;
+    struct regexp **rx = NULL;
+    int used = 0;
+
+    for (int i = 0; i < ns->used; i++) {
+        if (ns->nodes[i]->value != NULL)
+            used += 1;
+    }
+
+    if (used == 0) {
+        result = regexp_make_empty(info);
+    } else {
+        if (ALLOC_N(rx, ns->used) < 0)
+            goto error;
+        for (int i=0; i < ns->used; i++) {
+            if (ns->nodes[i]->value == NULL)
+                continue;
+
+            rx[i] = make_regexp_dup(info, ns->nodes[i]->value, 0);
+            if (rx[i] == NULL)
+                goto error;
+        }
+        result = regexp_union_n(info, ns->used, rx);
+    }
+
+ error:
+    if (rx != NULL) {
+        for (int i=0; i < ns->used; i++)
+            unref(rx[i], regexp);
+        free(rx);
+    }
+    return result;
+}
+
 static void func_regexp(struct state *state) {
     value_ind_t vind = make_value(T_REGEXP, state);
     int r;
 
     CHECK_ERROR;
 
-    struct value *str = pop_value(state);
-    assert(str->tag == T_STRING);
+    struct value *v = pop_value(state);
+    struct regexp *rx = NULL;
 
-    char *pat = strdup(str->string);
-    if (pat == NULL) {
-        STATE_ENOMEM;
-        return;
+    if (v->tag == T_STRING) {
+        rx = make_regexp_dup(state->error->info, v->string, 0);
+    } else if (v->tag == T_NODESET) {
+        rx = nodeset_as_regexp(state->error->info, v->nodeset);
+    } else {
+        assert(0);
     }
 
-    struct regexp *rx = make_regexp(NULL, pat, 0);
-    state->value_pool[vind].regexp = rx;
     if (rx == NULL) {
-        FREE(pat);
         STATE_ENOMEM;
         return;
     }
+
+    state->value_pool[vind].regexp = rx;
     r = regexp_compile(rx);
     if (r < 0) {
         const char *msg;
diff --git a/tests/xpath.tests b/tests/xpath.tests
index cd1909c..6f5e090 100644
--- a/tests/xpath.tests
+++ b/tests/xpath.tests
@@ -226,6 +226,13 @@ test regexp1 /files/etc/sysconfig/network-scripts/*[label() =~ regexp('.*-eth0')
 test regexp2 /files/etc/hosts/*[* =~ regexp('127\..*')]
      /files/etc/hosts/1
 
+test regexp3 /files/etc/hosts/*[ipaddr =~ regexp(/files/etc/hosts/*/ipaddr)]
+     /files/etc/hosts/1
+     /files/etc/hosts/2
+
+# Check that we don't crash when the nodeset contains all NULL's
+test regexp4 /files/etc/hosts/*[ipaddr =~ regexp(/files/etc/hosts/*[ipaddr])]
+
 # Union of nodesets
 test union (/files/etc/yum.conf | /files/etc/yum.repos.d/*)/*/gpgcheck
      /files/etc/yum.conf/main/gpgcheck = 1
-- 
1.7.4.4




More information about the augeas-devel mailing list