xpath FEATURE distinguish between traversed node and its value

... for xpath on schema.
Fixes #1538
diff --git a/src/xpath.c b/src/xpath.c
index 0a65830..0b65909 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -939,15 +939,16 @@
  * @brief Clear context of all schema nodes.
  *
  * @param[in] set Set to clear.
+ * @param[in] new_ctx New context state for all the nodes currently in the context.
  */
 static void
-set_scnode_clear_ctx(struct lyxp_set *set)
+set_scnode_clear_ctx(struct lyxp_set *set, int32_t new_ctx)
 {
     uint32_t i;
 
     for (i = 0; i < set->used; ++i) {
         if (set->val.scnodes[i].in_ctx == LYXP_SET_SCNODE_ATOM_CTX) {
-            set->val.scnodes[i].in_ctx = LYXP_SET_SCNODE_ATOM;
+            set->val.scnodes[i].in_ctx = new_ctx;
         } else if (set->val.scnodes[i].in_ctx == LYXP_SET_SCNODE_START) {
             set->val.scnodes[i].in_ctx = LYXP_SET_SCNODE_START_USED;
         }
@@ -1128,6 +1129,9 @@
             /* node is there, but update its status if needed */
             if (set1->val.scnodes[j].in_ctx == LYXP_SET_SCNODE_START_USED) {
                 set1->val.scnodes[j].in_ctx = set2->val.scnodes[i].in_ctx;
+            } else if ((set1->val.scnodes[j].in_ctx == LYXP_SET_SCNODE_ATOM_NODE) &&
+                    (set2->val.scnodes[i].in_ctx == LYXP_SET_SCNODE_ATOM_VAL)) {
+                set1->val.scnodes[j].in_ctx = set2->val.scnodes[i].in_ctx;
             }
         } else {
             memcpy(&set1->val.scnodes[set1->used], &set2->val.scnodes[i], sizeof *set2->val.scnodes);
@@ -3409,7 +3413,7 @@
                 LOGWRN(set->ctx, "Argument #2 of %s is node \"%s\", not of string-type.", __func__, sleaf->name);
             }
         }
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return rc;
     }
 
@@ -3454,7 +3458,7 @@
     LY_ERR rc;
 
     if (options & LYXP_SCNODE_ALL) {
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
         return LY_SUCCESS;
     }
 
@@ -3492,7 +3496,7 @@
                 LOGWRN(set->ctx, "Argument #1 of %s is node \"%s\", not of type \"decimal64\".", __func__, sleaf->name);
             }
         }
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return rc;
     }
 
@@ -3537,7 +3541,7 @@
                 }
             }
         }
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return rc;
     }
 
@@ -3597,7 +3601,7 @@
                 LOGWRN(set->ctx, "Argument #2 of %s is node \"%s\", not of string-type.", __func__, sleaf->name);
             }
         }
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return rc;
     }
 
@@ -3634,7 +3638,7 @@
         if (args[0]->type != LYXP_SET_SCNODE_SET) {
             LOGWRN(set->ctx, "Argument #1 of %s not a node-set as expected.", __func__);
         }
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
         return rc;
     }
 
@@ -3666,7 +3670,7 @@
     }
 
     if (options & LYXP_SCNODE_ALL) {
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
 
         LY_CHECK_RET(lyxp_set_scnode_insert_node(set, set->cur_scnode, LYXP_NODE_ELEM, NULL));
     } else {
@@ -3714,7 +3718,7 @@
                         __func__, sleaf->name);
             }
         }
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         if (sleaf && (sleaf->type->basetype == LY_TYPE_LEAFREF)) {
             lref = (struct lysc_type_leafref *)sleaf->type;
             oper = (sleaf->flags & LYS_IS_OUTPUT) ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT;
@@ -3802,7 +3806,7 @@
                 LOGWRN(set->ctx, "Argument #2 of %s is node \"%s\", not of string-type.", func, sleaf->name);
             }
         }
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return rc;
     }
 
@@ -3938,7 +3942,7 @@
                 LOGWRN(set->ctx, "Argument #1 of %s is node \"%s\", not of type \"enumeration\".", __func__, sleaf->name);
             }
         }
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return rc;
     }
 
@@ -3973,7 +3977,7 @@
 xpath_false(struct lyxp_set **UNUSED(args), uint16_t UNUSED(arg_count), struct lyxp_set *set, uint32_t options)
 {
     if (options & LYXP_SCNODE_ALL) {
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
         return LY_SUCCESS;
     }
 
@@ -4027,12 +4031,13 @@
     if (options & LYXP_SCNODE_ALL) {
         if ((args[0]->type == LYXP_SET_SCNODE_SET) && (sleaf = (struct lysc_node_leaf *)warn_get_scnode_in_ctx(args[0]))) {
             if (!(sleaf->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
-                LOGWRN(set->ctx, "Argument #1 of %s is a %s node \"%s\".", __func__, lys_nodetype2str(sleaf->nodetype), sleaf->name);
+                LOGWRN(set->ctx, "Argument #1 of %s is a %s node \"%s\".", __func__, lys_nodetype2str(sleaf->nodetype),
+                        sleaf->name);
             } else if (!warn_is_string_type(sleaf->type)) {
                 LOGWRN(set->ctx, "Argument #1 of %s is node \"%s\", not of string-type.", __func__, sleaf->name);
             }
         }
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return rc;
     }
 
@@ -4114,7 +4119,7 @@
 xpath_last(struct lyxp_set **UNUSED(args), uint16_t UNUSED(arg_count), struct lyxp_set *set, uint32_t options)
 {
     if (options & LYXP_SCNODE_ALL) {
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
         return LY_SUCCESS;
     }
 
@@ -4149,7 +4154,7 @@
     (void)options;
 
     if (options & LYXP_SCNODE_ALL) {
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
         return LY_SUCCESS;
     }
 
@@ -4220,7 +4225,7 @@
     const char *name = NULL;
 
     if (options & LYXP_SCNODE_ALL) {
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
         return LY_SUCCESS;
     }
 
@@ -4302,7 +4307,7 @@
     (void)options;
 
     if (options & LYXP_SCNODE_ALL) {
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return LY_SUCCESS;
     }
 
@@ -4374,7 +4379,7 @@
 xpath_node(struct lyxp_set **UNUSED(args), uint16_t UNUSED(arg_count), struct lyxp_set *set, uint32_t options)
 {
     if (options & LYXP_SCNODE_ALL) {
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
         return LY_SUCCESS;
     }
 
@@ -4405,14 +4410,16 @@
     LY_ERR rc = LY_SUCCESS;
 
     if (options & LYXP_SCNODE_ALL) {
-        if (arg_count && (args[0]->type == LYXP_SET_SCNODE_SET) && (sleaf = (struct lysc_node_leaf *)warn_get_scnode_in_ctx(args[0]))) {
+        if (arg_count && (args[0]->type == LYXP_SET_SCNODE_SET) &&
+                (sleaf = (struct lysc_node_leaf *)warn_get_scnode_in_ctx(args[0]))) {
             if (!(sleaf->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
-                LOGWRN(set->ctx, "Argument #1 of %s is a %s node \"%s\".", __func__, lys_nodetype2str(sleaf->nodetype), sleaf->name);
+                LOGWRN(set->ctx, "Argument #1 of %s is a %s node \"%s\".", __func__, lys_nodetype2str(sleaf->nodetype),
+                        sleaf->name);
             } else if (!warn_is_string_type(sleaf->type)) {
                 LOGWRN(set->ctx, "Argument #1 of %s is node \"%s\", not of string-type.", __func__, sleaf->name);
             }
         }
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return rc;
     }
 
@@ -4489,7 +4496,7 @@
 xpath_not(struct lyxp_set **args, uint16_t UNUSED(arg_count), struct lyxp_set *set, uint32_t options)
 {
     if (options & LYXP_SCNODE_ALL) {
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
         return LY_SUCCESS;
     }
 
@@ -4519,7 +4526,7 @@
     LY_ERR rc;
 
     if (options & LYXP_SCNODE_ALL) {
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return LY_SUCCESS;
     }
 
@@ -4549,7 +4556,7 @@
 xpath_position(struct lyxp_set **UNUSED(args), uint16_t UNUSED(arg_count), struct lyxp_set *set, uint32_t options)
 {
     if (options & LYXP_SCNODE_ALL) {
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
         return LY_SUCCESS;
     }
 
@@ -4603,7 +4610,7 @@
                 LOGWRN(set->ctx, "Argument #2 of %s is node \"%s\", not of string-type.", __func__, sleaf->name);
             }
         }
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return rc;
     }
 
@@ -4670,7 +4677,7 @@
                 LOGWRN(set->ctx, "Argument #1 of %s is node \"%s\", not of type \"decimal64\".", __func__, sleaf->name);
             }
         }
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return rc;
     }
 
@@ -4723,7 +4730,7 @@
                 LOGWRN(set->ctx, "Argument #2 of %s is node \"%s\", not of string-type.", __func__, sleaf->name);
             }
         }
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return rc;
     }
 
@@ -4757,7 +4764,7 @@
     LY_ERR rc;
 
     if (options & LYXP_SCNODE_ALL) {
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return LY_SUCCESS;
     }
 
@@ -4804,7 +4811,7 @@
                 LOGWRN(set->ctx, "Argument #0 of %s is node \"%s\", not of string-type.", __func__, sleaf->name);
             }
         }
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return rc;
     }
 
@@ -4867,7 +4874,7 @@
                 LOGWRN(set->ctx, "Argument #3 of %s is node \"%s\", not of numeric type.", __func__, sleaf->name);
             }
         }
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return rc;
     }
 
@@ -4952,7 +4959,7 @@
                 LOGWRN(set->ctx, "Argument #2 of %s is node \"%s\", not of string-type.", __func__, sleaf->name);
             }
         }
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return rc;
     }
 
@@ -5005,7 +5012,7 @@
                 LOGWRN(set->ctx, "Argument #2 of %s is node \"%s\", not of string-type.", __func__, sleaf->name);
             }
         }
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return rc;
     }
 
@@ -5058,7 +5065,7 @@
                 }
             }
         }
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return rc;
     }
 
@@ -5111,7 +5118,7 @@
     uint32_t i;
 
     if (options & LYXP_SCNODE_ALL) {
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return LY_SUCCESS;
     }
 
@@ -5188,7 +5195,7 @@
                 LOGWRN(set->ctx, "Argument #3 of %s is node \"%s\", not of string-type.", __func__, sleaf->name);
             }
         }
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         return rc;
     }
 
@@ -5257,7 +5264,7 @@
 xpath_true(struct lyxp_set **UNUSED(args), uint16_t UNUSED(arg_count), struct lyxp_set *set, uint32_t options)
 {
     if (options & LYXP_SCNODE_ALL) {
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
         return LY_SUCCESS;
     }
 
@@ -5353,7 +5360,7 @@
     }
 
     if (options & LYXP_SCNODE_ALL) {
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
         LY_CHECK_RET(lyxp_set_scnode_insert_node(set, NULL, set->root_type, NULL));
     } else {
         set->type = LYXP_SET_NODE_SET;
@@ -5685,7 +5692,7 @@
             /* remember context node */
             set->val.scnodes[i].in_ctx = LYXP_SET_SCNODE_START_USED;
         } else {
-            set->val.scnodes[i].in_ctx = LYXP_SET_SCNODE_ATOM;
+            set->val.scnodes[i].in_ctx = LYXP_SET_SCNODE_ATOM_NODE;
         }
 
         start_parent = set->val.scnodes[i].scnode;
@@ -5859,7 +5866,7 @@
             /* remember context node */
             set->val.scnodes[i].in_ctx = LYXP_SET_SCNODE_START_USED;
         } else {
-            set->val.scnodes[i].in_ctx = LYXP_SET_SCNODE_ATOM;
+            set->val.scnodes[i].in_ctx = LYXP_SET_SCNODE_ATOM_NODE;
         }
 
         /* TREE DFS */
@@ -6280,7 +6287,7 @@
             /* remember context node */
             set->val.scnodes[i].in_ctx = LYXP_SET_SCNODE_START_USED;
         } else {
-            set->val.scnodes[i].in_ctx = LYXP_SET_SCNODE_ATOM;
+            set->val.scnodes[i].in_ctx = LYXP_SET_SCNODE_ATOM_NODE;
         }
 
         start_parent = set->val.scnodes[i].scnode;
@@ -6435,7 +6442,7 @@
             /* remember context node */
             set->val.scnodes[i].in_ctx = LYXP_SET_SCNODE_START_USED;
         } else {
-            set->val.scnodes[i].in_ctx = LYXP_SET_SCNODE_ATOM;
+            set->val.scnodes[i].in_ctx = LYXP_SET_SCNODE_ATOM_NODE;
         }
 
         node = set->val.scnodes[i].scnode;
@@ -6849,7 +6856,7 @@
         /* restore the state as it was before the predicate */
         for (i = 0; i < set->used; ++i) {
             if (set->val.scnodes[i].in_ctx == LYXP_SET_SCNODE_ATOM_CTX) {
-                set->val.scnodes[i].in_ctx = LYXP_SET_SCNODE_ATOM;
+                set->val.scnodes[i].in_ctx = LYXP_SET_SCNODE_ATOM_NODE;
             } else if (set->val.scnodes[i].in_ctx == pred_in_ctx) {
                 set->val.scnodes[i].in_ctx = LYXP_SET_SCNODE_ATOM_CTX;
             }
@@ -7169,7 +7176,7 @@
     /* move to the attribute(s), data node(s), or schema node(s) */
     if (attr_axis) {
         if (set && (options & LYXP_SCNODE_ALL)) {
-            set_scnode_clear_ctx(set);
+            set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
         } else {
             if (all_desc) {
                 rc = moveto_attr_alldesc(set, moveto_mod, ncname_dict, options);
@@ -7190,7 +7197,7 @@
             LY_CHECK_GOTO(rc, cleanup);
 
             for (i = set->used - 1; i > -1; --i) {
-                if (set->val.scnodes[i].in_ctx > LYXP_SET_SCNODE_ATOM) {
+                if (set->val.scnodes[i].in_ctx > LYXP_SET_SCNODE_ATOM_NODE) {
                     break;
                 }
             }
@@ -7257,7 +7264,7 @@
     if (set) {
         assert(exp->tok_len[*tok_idx] == 4);
         if (set->type == LYXP_SET_SCNODE_SET) {
-            set_scnode_clear_ctx(set);
+            set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
             /* just for the debug message below */
             set = NULL;
         } else {
@@ -7652,7 +7659,7 @@
         if (options & LYXP_SCNODE_ALL) {
             /* merge all nodes from arg evaluations */
             for (i = 0; i < arg_count; ++i) {
-                set_scnode_clear_ctx(args[i]);
+                set_scnode_clear_ctx(args[i], LYXP_SET_SCNODE_ATOM_NODE);
                 lyxp_set_scnode_merge(set, args[i]);
             }
         }
@@ -7783,7 +7790,7 @@
         /* Literal */
         if (!set || (options & LYXP_SCNODE_ALL)) {
             if (set) {
-                set_scnode_clear_ctx(set);
+                set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
             }
             eval_literal(exp, tok_idx, NULL);
         } else {
@@ -7797,7 +7804,7 @@
         /* Number */
         if (!set || (options & LYXP_SCNODE_ALL)) {
             if (set) {
-                set_scnode_clear_ctx(set);
+                set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
             }
             rc = eval_number(NULL, exp, tok_idx, NULL);
         } else {
@@ -8006,7 +8013,7 @@
         if (options & LYXP_SCNODE_ALL) {
             warn_operands(set->ctx, set, &set2, 1, exp->expr, exp->tok_pos[this_op - 1]);
             lyxp_set_scnode_merge(set, &set2);
-            set_scnode_clear_ctx(set);
+            set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         } else {
             rc = moveto_op_math(set, &set2, &exp->expr[exp->tok_pos[this_op]]);
             LY_CHECK_GOTO(rc, cleanup);
@@ -8074,7 +8081,7 @@
         if (options & LYXP_SCNODE_ALL) {
             warn_operands(set->ctx, set, &set2, 1, exp->expr, exp->tok_pos[this_op - 1]);
             lyxp_set_scnode_merge(set, &set2);
-            set_scnode_clear_ctx(set);
+            set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         } else {
             rc = moveto_op_math(set, &set2, &exp->expr[exp->tok_pos[this_op]]);
             LY_CHECK_GOTO(rc, cleanup);
@@ -8144,7 +8151,7 @@
         if (options & LYXP_SCNODE_ALL) {
             warn_operands(set->ctx, set, &set2, 1, exp->expr, exp->tok_pos[this_op - 1]);
             lyxp_set_scnode_merge(set, &set2);
-            set_scnode_clear_ctx(set);
+            set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         } else {
             rc = moveto_op_comp(set, &set2, &exp->expr[exp->tok_pos[this_op]], options);
             LY_CHECK_GOTO(rc, cleanup);
@@ -8213,7 +8220,7 @@
             warn_equality_value(exp, set, *tok_idx - 1, this_op - 1, *tok_idx - 1);
             warn_equality_value(exp, &set2, this_op - 1, this_op - 1, *tok_idx - 1);
             lyxp_set_scnode_merge(set, &set2);
-            set_scnode_clear_ctx(set);
+            set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL);
         } else {
             rc = moveto_op_comp(set, &set2, &exp->expr[exp->tok_pos[this_op]], options);
             LY_CHECK_GOTO(rc, cleanup);
@@ -8257,7 +8264,7 @@
 
     /* cast to boolean, we know that will be the final result */
     if (set && (options & LYXP_SCNODE_ALL)) {
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
     } else {
         lyxp_set_cast(set, LYXP_SET_BOOLEAN);
     }
@@ -8282,7 +8289,7 @@
 
         /* eval - just get boolean value actually */
         if (set->type == LYXP_SET_SCNODE_SET) {
-            set_scnode_clear_ctx(&set2);
+            set_scnode_clear_ctx(&set2, LYXP_SET_SCNODE_ATOM_NODE);
             lyxp_set_scnode_merge(set, &set2);
         } else {
             lyxp_set_cast(&set2, LYXP_SET_BOOLEAN);
@@ -8327,7 +8334,7 @@
 
     /* cast to boolean, we know that will be the final result */
     if (set && (options & LYXP_SCNODE_ALL)) {
-        set_scnode_clear_ctx(set);
+        set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE);
     } else {
         lyxp_set_cast(set, LYXP_SET_BOOLEAN);
     }
@@ -8354,7 +8361,7 @@
 
         /* eval - just get boolean value actually */
         if (set->type == LYXP_SET_SCNODE_SET) {
-            set_scnode_clear_ctx(&set2);
+            set_scnode_clear_ctx(&set2, LYXP_SET_SCNODE_ATOM_NODE);
             lyxp_set_scnode_merge(set, &set2);
         } else {
             lyxp_set_cast(&set2, LYXP_SET_BOOLEAN);