[augeas-devel] augeas: master - * src/pathx.c: add relational expressions '>', '<', '>=', '<='
David Lutterkort
lutter at fedoraproject.org
Thu Feb 19 20:05:51 UTC 2009
Gitweb: http://git.fedorahosted.org/git/augeas.git?p=augeas.git;a=commitdiff;h=754bce2ecc8d7255674354d494fe3d926dd31059
Commit: 754bce2ecc8d7255674354d494fe3d926dd31059
Parent: 1c8f54acc28df867222319ed77b1bb053ae74ec4
Author: David Lutterkort <lutter at redhat.com>
AuthorDate: Wed Feb 18 12:03:31 2009 -0800
Committer: David Lutterkort <lutter at redhat.com>
CommitterDate: Wed Feb 18 14:58:45 2009 -0800
* src/pathx.c: add relational expressions '>', '<', '>=', '<='
---
src/pathx.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++--
tests/xpath.tests | 3 ++
2 files changed, 84 insertions(+), 3 deletions(-)
diff --git a/src/pathx.c b/src/pathx.c
index feca067..b9e0781 100644
--- a/src/pathx.c
+++ b/src/pathx.c
@@ -63,6 +63,10 @@ enum expr_tag {
enum binary_op {
OP_EQ, /* '=' */
OP_NEQ, /* '!=' */
+ OP_LT, /* '<' */
+ OP_LE, /* '<=' */
+ OP_GT, /* '>' */
+ OP_GE, /* '>=' */
OP_PLUS, /* '+' */
OP_MINUS, /* '-' */
OP_STAR /* '*' */
@@ -546,6 +550,36 @@ static void eval_arith(struct state *state, enum binary_op op) {
push_value(vind, state);
}
+static void eval_rel(struct state *state, bool greater, bool equal) {
+ struct value *r, *l;
+ int res;
+
+ /* We always check l < r or l <= r */
+ if (greater) {
+ l = pop_value(state);
+ r = pop_value(state);
+ } else {
+ r = pop_value(state);
+ l = pop_value(state);
+ }
+ if (l->tag == T_NUMBER) {
+ if (equal)
+ res = (l->number < r->number);
+ else
+ res = (l->number <= r->number);
+ } else if (l->tag == T_STRING) {
+ int cmp = strcmp(l->string, r->string);
+ if (equal)
+ res = cmp <= 0;
+ else
+ res = cmp < 0;
+ } else {
+ assert(0);
+ }
+
+ push_boolean_value(res, state);
+}
+
static void eval_binary(struct expr *expr, struct state *state) {
eval_expr(expr->left, state);
eval_expr(expr->right, state);
@@ -558,6 +592,18 @@ static void eval_binary(struct expr *expr, struct state *state) {
case OP_NEQ:
eval_eq(state, 1);
break;
+ case OP_LT:
+ eval_rel(state, false, false);
+ break;
+ case OP_LE:
+ eval_rel(state, false, true);
+ break;
+ case OP_GT:
+ eval_rel(state, true, false);
+ break;
+ case OP_GE:
+ eval_rel(state, true, true);
+ break;
case OP_MINUS:
case OP_PLUS:
case OP_STAR:
@@ -779,6 +825,9 @@ static void check_app(struct expr *expr, struct state *state) {
* T_NODESET -> T_STRING -> T_BOOLEAN
* T_NUMBER -> T_NUMBER -> T_BOOLEAN
*
+ * '>', '>=',
+ * '<', '<=' : T_NUMBER -> T_NUMBER -> T_BOOLEAN
+ * T_STRING -> T_STRING -> T_BOOLEAN
* '+', '-', '*': T_NUMBER -> T_NUMBER -> T_NUMBER
*
*/
@@ -800,6 +849,14 @@ static void check_binary(struct expr *expr, struct state *state) {
|| (l == T_NUMBER && r == T_NUMBER);;
res = T_BOOLEAN;
break;
+ case OP_LT:
+ case OP_LE:
+ case OP_GT:
+ case OP_GE:
+ ok = (l == T_NUMBER && r == T_NUMBER)
+ || (l == T_STRING && r == T_STRING);
+ res = T_BOOLEAN;
+ break;
case OP_PLUS:
case OP_MINUS:
case OP_STAR:
@@ -1379,18 +1436,39 @@ static void parse_additive_expr(struct state *state) {
}
/*
- * EqualityExpr ::= AdditiveExpr (EqualityOp AdditiveExpr)?
+ * RelationalExpr ::= AdditiveExpr (RelationalOp AdditiveExpr)?
+ * EqualityOp ::= ">" | "<" | ">=" | "<="
+ */
+static void parse_relational_expr(struct state *state) {
+ parse_additive_expr(state);
+ CHECK_ERROR;
+ if (*state->pos == '<' || *state->pos == '>') {
+ enum binary_op op = (*state->pos == '<') ? OP_LT : OP_GT;
+ state->pos += 1;
+ if (*state->pos == '=') {
+ op = (op == OP_LT) ? OP_LE : OP_GE;
+ state->pos += 1;
+ }
+ skipws(state);
+ parse_additive_expr(state);
+ CHECK_ERROR;
+ push_new_binary_op(op, state);
+ }
+}
+
+/*
+ * EqualityExpr ::= RelationalExpr (EqualityOp RelationalExpr)?
* EqualityOp ::= "=" | "!="
*/
static void parse_equality_expr(struct state *state) {
- parse_additive_expr(state);
+ parse_relational_expr(state);
CHECK_ERROR;
if (*state->pos == '=' ||
(*state->pos == '!' && state->pos[1] == '=')) {
enum binary_op op = (*state->pos == '=') ? OP_EQ : OP_NEQ;
state->pos += (op == OP_EQ) ? 1 : 2;
skipws(state);
- parse_additive_expr(state);
+ parse_relational_expr(state);
CHECK_ERROR;
push_new_binary_op(op, state);
}
diff --git a/tests/xpath.tests b/tests/xpath.tests
index 33685d6..bded6ff 100644
--- a/tests/xpath.tests
+++ b/tests/xpath.tests
@@ -151,3 +151,6 @@ test last-ssh-service /files/etc/services/service-name[port = '22'][last()]
test count-one-alias /files/etc/hosts/*[count(alias) = 1]
/files/etc/hosts/2
+
+test number-gt /files/etc/hosts/*[count(alias) > 2]
+ /files/etc/hosts/1
More information about the augeas-devel
mailing list