[augeas-devel] [PATCH 8/8] path expressions: allow concatenating strings and regexps with '+'

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


From: David Lutterkort <lutter at redhat.com>

---
 src/pathx.c       |   51 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 tests/xpath.tests |    3 +++
 2 files changed, 53 insertions(+), 1 deletions(-)

diff --git a/src/pathx.c b/src/pathx.c
index aadc449..e68580c 100644
--- a/src/pathx.c
+++ b/src/pathx.c
@@ -913,6 +913,42 @@ static void eval_union(struct state *state) {
     push_value(vind, state);
 }
 
+static void eval_concat_string(struct state *state) {
+    value_ind_t vind = make_value(T_STRING, state);
+    struct value *r = pop_value(state);
+    struct value *l = pop_value(state);
+    char *res = NULL;
+
+    CHECK_ERROR;
+
+    if (ALLOC_N(res, strlen(l->string) + strlen(r->string) + 1) < 0) {
+        STATE_ENOMEM;
+        return;
+    }
+    strcpy(res, l->string);
+    strcat(res, r->string);
+    state->value_pool[vind].string = res;
+    push_value(vind, state);
+}
+
+static void eval_concat_regexp(struct state *state) {
+    value_ind_t vind = make_value(T_REGEXP, state);
+    struct value *r = pop_value(state);
+    struct value *l = pop_value(state);
+    struct regexp *rx = NULL;
+
+    CHECK_ERROR;
+
+    rx = regexp_concat(state->error->info, l->regexp, r->regexp);
+    if (rx == NULL) {
+        STATE_ENOMEM;
+        return;
+    }
+
+    state->value_pool[vind].regexp = rx;
+    push_value(vind, state);
+}
+
 static void eval_re_match(struct state *state, enum binary_op op) {
     struct value *rx  = pop_value(state);
     struct value *v = pop_value(state);
@@ -958,8 +994,15 @@ static void eval_binary(struct expr *expr, struct state *state) {
     case OP_GE:
         eval_rel(state, true, true);
         break;
-    case OP_MINUS:
     case OP_PLUS:
+        if (expr->type == T_NUMBER)
+            eval_arith(state, expr->op);
+        else if (expr->type == T_STRING)
+            eval_concat_string(state);
+        else if (expr->type == T_REGEXP)
+            eval_concat_regexp(state);
+        break;
+    case OP_MINUS:
     case OP_STAR:
         eval_arith(state, expr->op);
         break;
@@ -1274,6 +1317,9 @@ static void check_app(struct expr *expr, struct state *state) {
  * '>', '>=',
  * '<', '<='  : T_NUMBER -> T_NUMBER -> T_BOOLEAN
  *              T_STRING -> T_STRING -> T_BOOLEAN
+ * '+'        : T_NUMBER -> T_NUMBER -> T_NUMBER
+ *              T_STRING -> T_STRING -> T_STRING
+ *              T_REGEXP -> T_REGEXP -> T_REGEXP
  * '+', '-', '*': T_NUMBER -> T_NUMBER -> T_NUMBER
  *
  * 'and', 'or': T_BOOLEAN -> T_BOOLEAN -> T_BOOLEAN
@@ -1311,6 +1357,9 @@ static void check_binary(struct expr *expr, struct state *state) {
         res = T_BOOLEAN;
         break;
     case OP_PLUS:
+        ok = (l == r && (l == T_NUMBER || l == T_STRING || l == T_REGEXP));
+        res = l;
+        break;
     case OP_MINUS:
     case OP_STAR:
         ok =  (l == T_NUMBER && r == T_NUMBER);
diff --git a/tests/xpath.tests b/tests/xpath.tests
index 8071568..e2c8ee7 100644
--- a/tests/xpath.tests
+++ b/tests/xpath.tests
@@ -248,6 +248,9 @@ test glob4 /augeas/load/*[ '/etc/hosts' =~ glob(incl) ]
 test glob_nomatch /files/etc/hosts/*[ipaddr][ ipaddr !~ glob(/files/etc/hosts/*/ipaddr[1]) ]
     /files/etc/hosts/2
 
+test glob_for_lens /augeas/load/*[ '/etc/hosts/1/ipaddr' =~ glob(incl) + regexp('/.*') ]/lens
+     /augeas/load/Hosts/lens = @Hosts
+
 # 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