compiled schema NEW when dummy node check
Also, no need to check it in data now.
diff --git a/src/common.h b/src/common.h
index a3403b5..9392b5c 100644
--- a/src/common.h
+++ b/src/common.h
@@ -183,6 +183,7 @@
#define LY_VCODE_INVAL_MINMAX LYVE_SEMANTICS, "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u."
#define LY_VCODE_CIRC_WHEN LYVE_SEMANTICS, "When condition of \"%s\" includes a self-reference (referenced by when of \"%s\")."
+#define LY_VCODE_DUMMY_WHEN LYVE_SEMANTICS, "When condition of \"%s\" is accessing its own conditional node."
#define LY_VCODE_INSTMT LYVE_SYNTAX_YANG, "Invalid keyword \"%s\"."
#define LY_VCODE_INCHILDSTMT LYVE_SYNTAX_YANG, "Invalid keyword \"%s\" as a child of \"%s\"."
@@ -220,7 +221,6 @@
#define LY_VCODE_XP_INARGCOUNT LYVE_XPATH, "Invalid number of arguments (%d) for the XPath function %.*s."
#define LY_VCODE_XP_INARGTYPE LYVE_XPATH, "Wrong type of argument #%d (%s) for the XPath function %s."
#define LY_VCODE_XP_INCTX LYVE_XPATH, "Invalid context type %s in %s."
-#define LY_VCODE_XP_DUMMY LYVE_XPATH, "Accessing the value of the dummy node \"%s\"."
#define LY_VCODE_XP_INOP_1 LYVE_XPATH, "Cannot apply XPath operation %s on %s."
#define LY_VCODE_XP_INOP_2 LYVE_XPATH, "Cannot apply XPath operation %s on %s and %s."
#define LY_VCODE_XP_INMOD LYVE_XPATH, "Unknown module \"%.*s\"."
diff --git a/src/tree_data.h b/src/tree_data.h
index 6820144..6e63d38 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -244,13 +244,13 @@
* ---------------------+-+-+-+-+-+-+-+
* 1 LYD_DEFAULT |x| |x|x| | | |
* +-+-+-+-+-+-+-+
- * 2 | | | | | | | |
+ * 2 LYD_WHEN_TRUE |x|x|x|x|x| | |
* ---------------------+-+-+-+-+-+-+-+
*
*/
-#define LYD_DEFAULT 0x01 /**< default (implicit) node; */
-#define LYD_DUMMY 0x80000000 /**< dummy node (in XPath context, internal flag) */
+#define LYD_DEFAULT 0x01 /**< default (implicit) node */
+#define LYD_WHEN_TRUE 0x02 /**< all when conditions of this node were evaluated to true */
/** @} */
/**
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index 574a49e..47e759f 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -4758,13 +4758,18 @@
if (!(ctx->options & LYSC_OPT_GROUPING)) {
/* do not check "when" semantics in a grouping */
- ly_set_add(&ctx->unres, target, 0);
+ ly_set_add(&ctx->unres, node, 0);
}
when_shared = *when;
} else {
++when_shared->refcount;
(*when) = when_shared;
+
+ if (!(ctx->options & LYSC_OPT_GROUPING)) {
+ /* in this case check "when" again for all children because of dummy node check */
+ ly_set_add(&ctx->unres, node, 0);
+ }
}
}
}
@@ -5040,6 +5045,11 @@
} else {
++when_shared->refcount;
(*when) = when_shared;
+
+ if (!(ctx->options & LYSC_OPT_GROUPING)) {
+ /* in this case check "when" again for all children because of dummy node check */
+ ly_set_add(&ctx->unres, child, 0);
+ }
}
}
}
@@ -6940,7 +6950,7 @@
* @return LY_ERR value
*/
static LY_ERR
-lys_compile_check_cyclic_when(struct lyxp_set *set, const struct lysc_node *node)
+lys_compile_check_when_cyclic(struct lyxp_set *set, const struct lysc_node *node)
{
struct lyxp_set tmp_set;
struct lyxp_set_scnode *xp_scnode;
@@ -6955,11 +6965,8 @@
for (i = 0; i < set->used; ++i) {
xp_scnode = &set->val.scnodes[i];
- if ((xp_scnode->type == LYXP_NODE_ELEM) && (xp_scnode->scnode == node)) {
- /* node when was already checked */
- xp_scnode->in_ctx = 2;
- } else {
- /* check node when */
+ if (xp_scnode->in_ctx != -1) {
+ /* check node when, skip the context node (it was just checked) */
xp_scnode->in_ctx = 1;
}
}
@@ -6993,7 +7000,7 @@
if (tmp_set.val.scnodes[j].type == LYXP_NODE_ELEM) {
/* try to find this node in our set */
idx = lyxp_set_scnode_dup_node_check(set, tmp_set.val.scnodes[j].scnode, LYXP_NODE_ELEM, -1);
- if ((idx > -1) && (set->val.scnodes[idx].in_ctx == 2)) {
+ if ((idx > -1) && (set->val.scnodes[idx].in_ctx == -1)) {
LOGVAL(set->ctx, LY_VLOG_LYS, node, LY_VCODE_CIRC_WHEN, node->name, set->val.scnodes[idx].scnode->name);
ret = LY_EVALID;
goto cleanup;
@@ -7016,7 +7023,7 @@
} while (node && (node->nodetype & (LYS_CASE | LYS_CHOICE)));
/* this node when was checked */
- xp_scnode->in_ctx = 2;
+ xp_scnode->in_ctx = -1;
}
cleanup:
@@ -7095,22 +7102,26 @@
ctx->path[0] = '\0';
lysc_path((struct lysc_node *)node, LYSC_PATH_LOG, ctx->path, LYSC_CTX_BUFSIZE);
for (j = 0; j < tmp_set.used; ++j) {
- /* skip roots'n'stuff, set in_ctx for when checking */
- if (tmp_set.val.scnodes[j].type == LYXP_NODE_ELEM) {
+ /* skip roots'n'stuff */
+ if ((tmp_set.val.scnodes[j].type == LYXP_NODE_ELEM) && (tmp_set.val.scnodes[j].in_ctx != -1)) {
struct lysc_node *schema = tmp_set.val.scnodes[j].scnode;
/* XPath expression cannot reference "lower" status than the node that has the definition */
ret = lysc_check_status(ctx, when[i]->flags, when[i]->module, node->name, schema->flags, schema->module,
schema->name);
LY_CHECK_GOTO(ret, cleanup);
+
+ /* check dummy node accessing */
+ if (schema == node) {
+ LOGVAL(ctx->ctx, LY_VLOG_LYS, node, LY_VCODE_DUMMY_WHEN, node->name);
+ ret = LY_EVALID;
+ goto cleanup;
+ }
}
}
- /* check dummy node accessing */
- /* TODO */
-
/* check cyclic dependencies */
- ret = lys_compile_check_cyclic_when(&tmp_set, node);
+ ret = lys_compile_check_when_cyclic(&tmp_set, node);
LY_CHECK_GOTO(ret, cleanup);
lyxp_set_cast(&tmp_set, LYXP_SET_EMPTY);
diff --git a/src/xpath.c b/src/xpath.c
index 995941c..93dd7f6 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -502,11 +502,6 @@
{
int dynamic;
- if ((set->val.nodes[0].type != LYXP_NODE_ATTR) && (set->val.nodes[0].node->flags & LYD_DUMMY)) {
- LOGVAL(set->ctx, LY_VLOG_LYD, set->val.nodes[0].node, LY_VCODE_XP_DUMMY, set->val.nodes[0].node->schema->name);
- return LY_EVALID;
- }
-
switch (set->val.nodes[0].type) {
case LYXP_NODE_ROOT:
case LYXP_NODE_ROOT_CONFIG:
@@ -924,6 +919,8 @@
for (i = 0; i < set->used; ++i) {
if (set->val.scnodes[i].in_ctx == 1) {
set->val.scnodes[i].in_ctx = 0;
+ } else if (set->val.scnodes[i].in_ctx == -2) {
+ set->val.scnodes[i].in_ctx = -1;
}
}
}
@@ -1223,10 +1220,11 @@
* @param[in] set Set to modify.
* @return New context value.
*/
-static uint32_t
+static int32_t
set_scnode_new_in_ctx(struct lyxp_set *set)
{
- uint32_t ret_ctx, i;
+ uint32_t i;
+ int32_t ret_ctx;
assert(set->type == LYXP_SET_SCNODE_SET);
@@ -4969,6 +4967,8 @@
return LY_EVALID;
}
+ set_init(&set_item, set);
+
set_item.type = LYXP_SET_NODE_SET;
set_item.val.nodes = malloc(sizeof *set_item.val.nodes);
LY_CHECK_ERR_RET(!set_item.val.nodes, LOGMEM(set->ctx), LY_EMEM);
@@ -5022,10 +5022,6 @@
for (i = 0; i < set->used;) {
switch (set->val.nodes[i].type) {
case LYXP_NODE_ELEM:
- if (set->val.nodes[i].node->flags & LYD_DUMMY) {
- LOGVAL(set->ctx, LY_VLOG_LYD, set->val.nodes[i].node, LY_VCODE_XP_DUMMY, set->val.nodes[i].node->schema->name);
- return LY_EVALID;
- }
if (set->val.nodes[i].node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
set->val.nodes[i].type = LYXP_NODE_TEXT;
++i;
@@ -5278,8 +5274,8 @@
return LY_ENOT;
}
- /* dummy and context check */
- if ((node->flags & LYD_DUMMY) || ((root_type == LYXP_NODE_ROOT_CONFIG) && (node->schema->flags & LYS_CONFIG_R))) {
+ /* context check */
+ if ((root_type == LYXP_NODE_ROOT_CONFIG) && (node->schema->flags & LYS_CONFIG_R)) {
return LY_EINVAL;
}
@@ -5389,9 +5385,8 @@
}
}
- /* skip nodes without children - leaves, leaflists, anyxmls, and dummy nodes (ouput root will eval to true) */
- } else if (!(set->val.nodes[i].node->flags & LYD_DUMMY)
- && !(set->val.nodes[i].node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
+ /* skip nodes without children - leaves, leaflists, anyxmls (ouput root will eval to true) */
+ } else if (!(set->val.nodes[i].node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
for (sub = lyd_node_children(set->val.nodes[i].node); sub; sub = sub->next) {
rc = moveto_node_check(sub, set->root_type, name_dict, moveto_mod);
@@ -5464,9 +5459,13 @@
orig_used = set->used;
for (i = 0; i < orig_used; ++i) {
if (set->val.scnodes[i].in_ctx != 1) {
- continue;
+ if (set->val.scnodes[i].in_ctx != -2) {
+ continue;
+ }
+
+ /* remember context node */
+ set->val.scnodes[i].in_ctx = -1;
}
- set->val.scnodes[i].in_ctx = 0;
start_parent = set->val.scnodes[i].scnode;
@@ -5657,9 +5656,13 @@
orig_used = set->used;
for (i = 0; i < orig_used; ++i) {
if (set->val.scnodes[i].in_ctx != 1) {
- continue;
+ if (set->val.scnodes[i].in_ctx != -2) {
+ continue;
+ }
+
+ /* remember context node */
+ set->val.scnodes[i].in_ctx = -1;
}
- set->val.scnodes[i].in_ctx = 0;
/* TREE DFS */
start = set->val.scnodes[i].scnode;
@@ -5757,7 +5760,7 @@
/* only attributes of an elem (not dummy) can be in the result, skip all the rest;
* our attributes are always qualified */
- if ((set->val.nodes[i].type == LYXP_NODE_ELEM) && !(set->val.nodes[i].node->flags & LYD_DUMMY)) {
+ if (set->val.nodes[i].type == LYXP_NODE_ELEM) {
for (sub = set->val.nodes[i].node->attr; sub; sub = sub->next) {
/* check "namespace" */
@@ -5950,7 +5953,7 @@
set_insert_node(to_set, parent, 0, LYXP_NODE_ELEM, to_set->used);
/* skip anydata/anyxml and dummy nodes */
- if (!(parent->schema->nodetype & LYS_ANYDATA) && !(parent->flags & LYD_DUMMY)) {
+ if (!(parent->schema->nodetype & LYS_ANYDATA)) {
/* also add all the children of this node, recursively */
rc = moveto_self_add_children_r(parent, 0, LYXP_NODE_ELEM, to_set, dup_check_set, options);
LY_CHECK_RET(rc);
@@ -5974,8 +5977,8 @@
if (!set_dup_node_check(dup_check_set, sub, LYXP_NODE_ELEM, -1)) {
set_insert_node(to_set, sub, 0, LYXP_NODE_ELEM, to_set->used);
- /* skip anydata/anyxml and dummy nodes */
- if ((sub->schema->nodetype & LYS_ANYDATA) || (sub->flags & LYD_DUMMY)) {
+ /* skip anydata/anyxml nodes */
+ if (sub->schema->nodetype & LYS_ANYDATA) {
continue;
}
@@ -6040,8 +6043,8 @@
continue;
}
- /* skip anydata/anyxml and dummy nodes */
- if ((set->val.nodes[i].node->schema->nodetype & LYS_ANYDATA) || (set->val.nodes[i].node->flags & LYD_DUMMY)) {
+ /* skip anydata/anyxml nodes */
+ if (set->val.nodes[i].node->schema->nodetype & LYS_ANYDATA) {
continue;
}
@@ -6095,7 +6098,12 @@
/* add all the children, they get added recursively */
for (i = 0; i < set->used; ++i) {
if (set->val.scnodes[i].in_ctx != 1) {
- continue;
+ if (set->val.scnodes[i].in_ctx != -2) {
+ continue;
+ }
+
+ /* remember context node (it was traversed again so it changes to a normal node) */
+ set->val.scnodes[i].in_ctx = 1;
}
/* add all the children */
@@ -6239,9 +6247,13 @@
orig_used = set->used;
for (i = 0; i < orig_used; ++i) {
if (set->val.scnodes[i].in_ctx != 1) {
- continue;
+ if (set->val.scnodes[i].in_ctx != -2) {
+ continue;
+ }
+
+ /* remember context node */
+ set->val.scnodes[i].in_ctx = -1;
}
- set->val.scnodes[i].in_ctx = 0;
node = set->val.scnodes[i].scnode;
@@ -6613,7 +6625,7 @@
if ((rc == LY_SUCCESS) && set && (options & LYXP_SCNODE_ALL)) {
for (i = set->used - 1; i > -1; --i) {
- if (set->val.scnodes[i].in_ctx) {
+ if (set->val.scnodes[i].in_ctx > 0) {
break;
}
}
@@ -6692,7 +6704,8 @@
{
LY_ERR rc;
uint16_t i, orig_exp;
- uint32_t orig_pos, orig_size, pred_in_ctx;
+ uint32_t orig_pos, orig_size;
+ int32_t pred_in_ctx;
struct lyxp_set set2;
struct lyd_node *orig_parent;
@@ -8307,6 +8320,7 @@
memset(set, 0, sizeof *set);
set->type = LYXP_SET_SCNODE_SET;
lyxp_set_scnode_insert_node(set, ctx_scnode, ctx_scnode_type);
+ set->val.scnodes[0].in_ctx = -2;
set->ctx = ctx;
set->ctx_scnode = ctx_scnode;
set->root_type = lyxp_get_root_type(NULL, ctx_scnode, options);
diff --git a/src/xpath.h b/src/xpath.h
index 1e27ab1..a0e45a1 100644
--- a/src/xpath.h
+++ b/src/xpath.h
@@ -214,11 +214,13 @@
struct lyxp_set_scnode {
struct lysc_node *scnode;
enum lyxp_node_type type;
- /* 0 - scnode was traversed, but not currently in the context,
- * 1 - scnode currently in context,
- * 2 - scnode in context and just added, so skip it for the current operation,
+ /* -2 - scnode not traversed, currently (the only node) in context;
+ * -1 - scnode not traversed except for the eval start, not currently in the context;
+ * 0 - scnode was traversed, but not currently in the context;
+ * 1 - scnode currently in context;
+ * 2 - scnode in context and just added, so skip it for the current operation;
* >=3 - scnode is not in context because we are in a predicate and this scnode was used/will be used later */
- uint32_t in_ctx;
+ int32_t in_ctx;
} *scnodes;
struct lyxp_set_attr {
struct lyd_attr *attr;