[augeas-devel] augeas: master - * src/pathx.c: coerce the operands of 'and'/'or' to boolean
David Lutterkort
lutter at fedoraproject.org
Fri Jun 5 20:13:17 UTC 2009
Gitweb: http://git.fedorahosted.org/git/augeas.git?p=augeas.git;a=commitdiff;h=41320231f5b0de775817fea366f699abcdcc5894
Commit: 41320231f5b0de775817fea366f699abcdcc5894
Parent: 241dc47cc4f1de1ae7dfced9707164da142c7e00
Author: David Lutterkort <lutter at redhat.com>
AuthorDate: Fri Jun 5 12:02:29 2009 -0700
Committer: David Lutterkort <lutter at redhat.com>
CommitterDate: Fri Jun 5 12:02:29 2009 -0700
* src/pathx.c: coerce the operands of 'and'/'or' to boolean
Fixes bug #44
---
src/pathx.c | 30 +++++++++++++++++++++++++++---
tests/xpath.tests | 9 +++++++++
2 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/src/pathx.c b/src/pathx.c
index 20209fa..d44aeb7 100644
--- a/src/pathx.c
+++ b/src/pathx.c
@@ -597,6 +597,26 @@ static void func_label(struct state *state) {
push_value(vind, state);
}
+static bool coerce_to_bool(struct value *v) {
+ switch (v->tag) {
+ case T_NODESET:
+ return v->nodeset->used > 0;
+ break;
+ case T_BOOLEAN:
+ return v->boolval;
+ break;
+ case T_NUMBER:
+ return v->number > 0;
+ break;
+ case T_STRING:
+ return strlen(v->string) > 0;
+ break;
+ default:
+ assert(0);
+ }
+ assert(0);
+}
+
static int calc_eq_nodeset_nodeset(struct nodeset *ns1, struct nodeset *ns2,
int neq) {
for (int i1=0; i1 < ns1->used; i1++) {
@@ -715,11 +735,14 @@ static void eval_rel(struct state *state, bool greater, bool equal) {
static void eval_and_or(struct state *state, enum binary_op op) {
struct value *r = pop_value(state);
struct value *l = pop_value(state);
+ bool left = coerce_to_bool(l);
+ bool right = coerce_to_bool(r);
+
if (op == OP_AND)
- push_boolean_value(l->boolval && r->boolval, state);
+ push_boolean_value(left && right, state);
else
- push_boolean_value(l->boolval || r->boolval, state);
+ push_boolean_value(left || right, state);
}
static void eval_binary(struct expr *expr, struct state *state) {
@@ -1033,6 +1056,7 @@ static void check_app(struct expr *expr, struct state *state) {
*
* 'and', 'or': T_BOOLEAN -> T_BOOLEAN -> T_BOOLEAN
*
+ * Any type can be coerced to T_BOOLEAN (see coerce_to_bool)
*/
static void check_binary(struct expr *expr, struct state *state) {
check_expr(expr->left, state);
@@ -1068,7 +1092,7 @@ static void check_binary(struct expr *expr, struct state *state) {
break;
case OP_AND:
case OP_OR:
- ok = (l == T_BOOLEAN && r == T_BOOLEAN);
+ ok = 1;
res = T_BOOLEAN;
break;
default:
diff --git a/tests/xpath.tests b/tests/xpath.tests
index 9926c3e..df31bff 100644
--- a/tests/xpath.tests
+++ b/tests/xpath.tests
@@ -188,3 +188,12 @@ test str-neq /files/etc/*['foo' != 'foo']
test label-neq /files/etc/hosts/*[label() != '#comment']
/files/etc/hosts/1
/files/etc/hosts/2
+
+# 'and' and 'or' need to coerce types to boolean
+test coerce-or /files[/files/etc/hosts/*[ipaddr = '127.0.0.1'] or /files/etc/aliases/*[name = 'root'] ]
+ /files
+
+test coerce-and-true /files['foo' and count(/files/etc/hosts/*) ]
+ /files
+
+test coerce-and-false /files['' and count(/none) and /none]
More information about the augeas-devel
mailing list