[augeas-devel] [PATCH 7/8] path expressions: add operator '!~'

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


From: David Lutterkort <lutter at redhat.com>

---
 doc/xpath.txt     |    3 ++-
 src/pathx.c       |   21 ++++++++++++++-------
 tests/xpath.tests |    3 +++
 3 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/doc/xpath.txt b/doc/xpath.txt
index a609003..2dc2be5 100644
--- a/doc/xpath.txt
+++ b/doc/xpath.txt
@@ -122,7 +122,8 @@ FunctionCall ::= Name '(' ( Expr ( ',' Expr )* )? ')'
 
 Expr ::= EqualityExpr
 EqualityExpr ::= RelationalExpr (EqualityOp RelationalExpr)? | ReMatchExpr
-ReMatchExpr ::= RelationalExpr "=~" RelationalExpr
+ReMatchExpr ::= RelationalExpr MatchOp RelationalExpr
+MatchOp ::= "=~" | "!~"
 EqualityOp ::= "=" | "!="
 RelationalExpr ::= AdditiveExpr (RelationalOp AdditiveExpr)?
 RelationalOp ::= ">" | "<" | ">=" | "<="
diff --git a/src/pathx.c b/src/pathx.c
index f49dd7b..aadc449 100644
--- a/src/pathx.c
+++ b/src/pathx.c
@@ -85,6 +85,7 @@ enum binary_op {
     OP_AND,        /* 'and' */
     OP_OR,         /* 'or' */
     OP_RE_MATCH,   /* '=~' */
+    OP_RE_NOMATCH, /* '!~' */
     OP_UNION       /* '|' */
 };
 
@@ -912,7 +913,7 @@ static void eval_union(struct state *state) {
     push_value(vind, state);
 }
 
-static void eval_re_match(struct state *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);
 
@@ -928,6 +929,8 @@ static void eval_re_match(struct state *state) {
             CHECK_ERROR;
         }
     }
+    if (op == OP_RE_NOMATCH)
+        result = !result;
     push_boolean_value(result, state);
 }
 
@@ -968,7 +971,8 @@ static void eval_binary(struct expr *expr, struct state *state) {
         eval_union(state);
         break;
     case OP_RE_MATCH:
-        eval_re_match(state);
+    case OP_RE_NOMATCH:
+        eval_re_match(state, expr->op);
         break;
     default:
         assert(0);
@@ -1273,7 +1277,7 @@ static void check_app(struct expr *expr, struct state *state) {
  * '+', '-', '*': T_NUMBER -> T_NUMBER -> T_NUMBER
  *
  * 'and', 'or': T_BOOLEAN -> T_BOOLEAN -> T_BOOLEAN
- * '=~'       : T_STRING  -> T_REGEXP  -> T_BOOLEAN
+ * '=~', '!~' : T_STRING  -> T_REGEXP  -> T_BOOLEAN
  *              T_NODESET -> T_REGEXP  -> T_BOOLEAN
  *
  * '|'        : T_NODESET -> T_NODESET -> T_NODESET
@@ -1322,6 +1326,7 @@ static void check_binary(struct expr *expr, struct state *state) {
         res = T_BOOLEAN;
         break;
     case OP_RE_MATCH:
+    case OP_RE_NOMATCH:
         ok = ((l == T_STRING || l == T_NODESET) && r == T_REGEXP);
         res = T_BOOLEAN;
         break;
@@ -1460,7 +1465,7 @@ static void push_new_binary_op(enum binary_op op, struct state *state) {
  * Name ::= NameNoWS NameWS* NameNoWS | NameNoWS
  */
 static char *parse_name(struct state *state) {
-    static const char const follow[] = "][|/=()";
+    static const char const follow[] = "][|/=()!";
     const char *s = state->pos;
     char *result;
 
@@ -2060,17 +2065,19 @@ static void parse_relational_expr(struct state *state) {
 /*
  * EqualityExpr ::= RelationalExpr (EqualityOp RelationalExpr)? | ReMatchExpr
  * EqualityOp ::= "=" | "!="
- * ReMatchExpr ::= RelationalExpr "=~" RelationalExpr
+ * ReMatchExpr ::= RelationalExpr MatchOp RelationalExpr
+ * MatchOp ::= "=~" | "!~"
  */
 static void parse_equality_expr(struct state *state) {
     parse_relational_expr(state);
     CHECK_ERROR;
-    if (*state->pos == '=' && state->pos[1] == '~') {
+    if ((*state->pos == '=' || *state->pos == '!') && state->pos[1] == '~') {
+        enum binary_op op = (*state->pos == '=') ? OP_RE_MATCH : OP_RE_NOMATCH;
         state->pos += 2;
         skipws(state);
         parse_relational_expr(state);
         CHECK_ERROR;
-        push_new_binary_op(OP_RE_MATCH, state);
+        push_new_binary_op(op, state);
     } else if (*state->pos == '=' ||
         (*state->pos == '!' && state->pos[1] == '=')) {
         enum binary_op op = (*state->pos == '=') ? OP_EQ : OP_NEQ;
diff --git a/tests/xpath.tests b/tests/xpath.tests
index 5bb0a23..8071568 100644
--- a/tests/xpath.tests
+++ b/tests/xpath.tests
@@ -245,6 +245,9 @@ test glob3 /files[ '^a' =~ glob('^a') ]
 test glob4 /augeas/load/*[ '/etc/hosts' =~ glob(incl) ]
      /augeas/load/Hosts
 
+test glob_nomatch /files/etc/hosts/*[ipaddr][ ipaddr !~ glob(/files/etc/hosts/*/ipaddr[1]) ]
+    /files/etc/hosts/2
+
 # 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