[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