[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