schema tree REFACTOR evaluate features during compilation
So that the compiled schema tree reflects the state
of all the features.
diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c
index 803fec2..a391fa1 100644
--- a/src/schema_compile_node.c
+++ b/src/schema_compile_node.c
@@ -37,6 +37,7 @@
#include "plugins_types.h"
#include "schema_compile.h"
#include "schema_compile_amend.h"
+#include "schema_features.h"
#include "set.h"
#include "tree.h"
#include "tree_data.h"
@@ -69,6 +70,10 @@
struct lysc_unres_dflt *r = NULL;
uint32_t i;
+ if (ctx->options & LYS_COMPILE_DISABLED) {
+ return LY_SUCCESS;
+ }
+
for (i = 0; i < ctx->dflts.count; ++i) {
if (((struct lysc_unres_dflt *)ctx->dflts.objs[i])->leaf == leaf) {
/* just replace the default */
@@ -113,6 +118,10 @@
struct lysc_unres_dflt *r = NULL;
uint32_t i;
+ if (ctx->options & LYS_COMPILE_DISABLED) {
+ return LY_SUCCESS;
+ }
+
for (i = 0; i < ctx->dflts.count; ++i) {
if (((struct lysc_unres_dflt *)ctx->dflts.objs[i])->llist == llist) {
/* just replace the defaults */
@@ -275,7 +284,7 @@
/* compile when */
LY_CHECK_RET(lys_compile_when_(ctx, when_p, flags, ctx_node, new_when));
- if (!(ctx->options & LYS_COMPILE_GROUPING)) {
+ if (!(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
/* do not check "when" semantics in a grouping */
LY_CHECK_RET(ly_set_add(&ctx->xpath, node, 0, NULL));
}
@@ -289,7 +298,7 @@
++(*when_c)->refcount;
*new_when = *when_c;
- if (!(ctx->options & LYS_COMPILE_GROUPING)) {
+ if (!(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
/* in this case check "when" again for all children because of dummy node check */
LY_CHECK_RET(ly_set_add(&ctx->xpath, node, 0, NULL));
}
@@ -1154,9 +1163,10 @@
{
LY_ERR ret = LY_SUCCESS;
LY_ARRAY_COUNT_TYPE u, v, match = 0;
- int32_t value = 0;
- uint32_t position = 0;
+ int32_t value = 0, cur_val;
+ uint32_t position = 0, cur_pos;
struct lysc_type_bitenum_item *e, storage;
+ ly_bool enabled;
if (base_enums && (ctx->pmod->version < LYS_VERSION_1_1)) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "%s type can be subtyped only in YANG 1.1 modules.",
@@ -1165,48 +1175,43 @@
}
LY_ARRAY_FOR(enums_p, u) {
- LY_ARRAY_NEW_RET(ctx->ctx, *enums, e, LY_EMEM);
- DUP_STRING_GOTO(ctx->ctx, enums_p[u].name, e->name, ret, done);
- DUP_STRING_GOTO(ctx->ctx, enums_p[u].ref, e->dsc, ret, done);
- DUP_STRING_GOTO(ctx->ctx, enums_p[u].ref, e->ref, ret, done);
- e->flags = enums_p[u].flags & LYS_FLAGS_COMPILED_MASK;
+ /* perform all checks */
if (base_enums) {
/* check the enum/bit presence in the base type - the set of enums/bits in the derived type must be a subset */
LY_ARRAY_FOR(base_enums, v) {
- if (!strcmp(e->name, base_enums[v].name)) {
+ if (!strcmp(enums_p[u].name, base_enums[v].name)) {
break;
}
}
if (v == LY_ARRAY_COUNT(base_enums)) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
"Invalid %s - derived type adds new item \"%s\".",
- basetype == LY_TYPE_ENUM ? "enumeration" : "bits", e->name);
+ basetype == LY_TYPE_ENUM ? "enumeration" : "bits", enums_p[u].name);
return LY_EVALID;
}
match = v;
}
if (basetype == LY_TYPE_ENUM) {
- e->flags |= LYS_ISENUM;
if (enums_p[u].flags & LYS_SET_VALUE) {
- e->value = (int32_t)enums_p[u].value;
- if (!u || (e->value >= value)) {
- value = e->value + 1;
+ cur_val = (int32_t)enums_p[u].value;
+ if (!u || (cur_val >= value)) {
+ value = cur_val + 1;
}
/* check collision with other values */
- for (v = 0; v < LY_ARRAY_COUNT(*enums) - 1; ++v) {
- if (e->value == (*enums)[v].value) {
+ LY_ARRAY_FOR(*enums, v) {
+ if (cur_val == (*enums)[v].value) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
"Invalid enumeration - value %d collide in items \"%s\" and \"%s\".",
- e->value, e->name, (*enums)[v].name);
+ cur_val, enums_p[u].name, (*enums)[v].name);
return LY_EVALID;
}
}
} else if (base_enums) {
/* inherit the assigned value */
- e->value = base_enums[match].value;
- if (!u || (e->value >= value)) {
- value = e->value + 1;
+ cur_val = base_enums[match].value;
+ if (!u || (cur_val >= value)) {
+ value = cur_val + 1;
}
} else {
/* assign value automatically */
@@ -1214,31 +1219,31 @@
/* counter overflow */
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
"Invalid enumeration - it is not possible to auto-assign enum value for "
- "\"%s\" since the highest value is already 2147483647.", e->name);
+ "\"%s\" since the highest value is already 2147483647.", enums_p[u].name);
return LY_EVALID;
}
- e->value = value++;
+ cur_val = value++;
}
} else { /* LY_TYPE_BITS */
if (enums_p[u].flags & LYS_SET_VALUE) {
- e->value = (int32_t)enums_p[u].value;
- if (!u || ((uint32_t)e->value >= position)) {
- position = (uint32_t)e->value + 1;
+ cur_pos = (uint32_t)enums_p[u].value;
+ if (!u || (cur_pos >= position)) {
+ position = cur_pos + 1;
}
/* check collision with other values */
- for (v = 0; v < LY_ARRAY_COUNT(*enums) - 1; ++v) {
- if (e->value == (*enums)[v].value) {
+ LY_ARRAY_FOR(*enums, v) {
+ if (cur_pos == (*enums)[v].position) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
"Invalid bits - position %u collide in items \"%s\" and \"%s\".",
- (uint32_t)e->value, e->name, (*enums)[v].name);
+ cur_pos, enums_p[u].name, (*enums)[v].name);
return LY_EVALID;
}
}
} else if (base_enums) {
/* inherit the assigned value */
- e->value = base_enums[match].value;
- if (!u || ((uint32_t)e->value >= position)) {
- position = (uint32_t)e->value + 1;
+ cur_pos = base_enums[match].position;
+ if (!u || (cur_pos >= position)) {
+ position = cur_pos + 1;
}
} else {
/* assign value automatically */
@@ -1246,31 +1251,51 @@
/* counter overflow */
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
"Invalid bits - it is not possible to auto-assign bit position for "
- "\"%s\" since the highest value is already 4294967295.", e->name);
+ "\"%s\" since the highest value is already 4294967295.", enums_p[u].name);
return LY_EVALID;
}
- e->value = position++;
+ cur_pos = position++;
}
}
+ /* the assigned values must not change from the derived type */
if (base_enums) {
- /* the assigned values must not change from the derived type */
- if (e->value != base_enums[match].value) {
- if (basetype == LY_TYPE_ENUM) {
+ if (basetype == LY_TYPE_ENUM) {
+ if (cur_val != base_enums[match].value) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
"Invalid enumeration - value of the item \"%s\" has changed from %d to %d in the derived type.",
- e->name, base_enums[match].value, e->value);
- } else {
+ enums_p[u].name, base_enums[match].value, cur_val);
+ return LY_EVALID;
+ }
+ } else {
+ if (cur_pos != base_enums[match].position) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
"Invalid bits - position of the item \"%s\" has changed from %u to %u in the derived type.",
- e->name, (uint32_t)base_enums[match].value, (uint32_t)e->value);
+ enums_p[u].name, base_enums[match].position, cur_pos);
+ return LY_EVALID;
}
- return LY_EVALID;
}
}
- COMPILE_ARRAY_GOTO(ctx, enums_p[u].iffeatures, e->iffeatures, v, lys_compile_iffeature, ret, done);
- COMPILE_EXTS_GOTO(ctx, enums_p[u].exts, e->exts, e, basetype == LY_TYPE_ENUM ? LYEXT_PAR_TYPE_ENUM : LYEXT_PAR_TYPE_BIT, ret, done);
+ /* evaluate if-ffeatures */
+ LY_CHECK_RET(lys_eval_iffeatures(ctx->ctx, enums_p[u].iffeatures, &enabled));
+ if (!enabled) {
+ continue;
+ }
+
+ /* add new enum/bit */
+ LY_ARRAY_NEW_RET(ctx->ctx, *enums, e, LY_EMEM);
+ DUP_STRING_GOTO(ctx->ctx, enums_p[u].name, e->name, ret, done);
+ DUP_STRING_GOTO(ctx->ctx, enums_p[u].dsc, e->dsc, ret, done);
+ DUP_STRING_GOTO(ctx->ctx, enums_p[u].ref, e->ref, ret, done);
+ e->flags = (enums_p[u].flags & LYS_FLAGS_COMPILED_MASK) | (basetype == LY_TYPE_ENUM ? LYS_ISENUM : 0);
+ if (basetype == LY_TYPE_ENUM) {
+ e->value = cur_val;
+ } else {
+ e->position = cur_pos;
+ }
+ COMPILE_EXTS_GOTO(ctx, enums_p[u].exts, e->exts, e, basetype == LY_TYPE_ENUM ? LYEXT_PAR_TYPE_ENUM :
+ LYEXT_PAR_TYPE_BIT, ret, done);
if (basetype == LY_TYPE_BITS) {
/* keep bits ordered by position */
@@ -1465,7 +1490,7 @@
}
return LY_EVALID;
}
- LY_CHECK_RET(lys_compile_identity_bases(ctx, type_p->pmod, type_p->bases, NULL, &idref->bases));
+ LY_CHECK_RET(lys_compile_identity_bases(ctx, type_p->pmod, type_p->bases, NULL, &idref->bases, NULL));
}
if (!base && !type_p->flags) {
@@ -1985,7 +2010,7 @@
parent = lysc_data_parent(parent);
}
- getnext_flags = LYS_GETNEXT_NOSTATECHECK | LYS_GETNEXT_WITHCHOICE;
+ getnext_flags = LYS_GETNEXT_WITHCHOICE;
if (parent && (parent->nodetype & (LYS_RPC | LYS_ACTION)) && (exclude->flags & LYS_CONFIG_R)) {
getnext_flags |= LYS_GETNEXT_OUTPUT;
}
@@ -1999,7 +2024,7 @@
/* we must compare with both the choice and all its nested data-definiition nodes (but not recursively) */
if (iter->nodetype == LYS_CHOICE) {
iter2 = NULL;
- while ((iter2 = lys_getnext(iter2, iter, NULL, LYS_GETNEXT_NOSTATECHECK))) {
+ while ((iter2 = lys_getnext(iter2, iter, NULL, 0))) {
if (CHECK_NODE(iter2, exclude, name)) {
goto error;
}
@@ -2037,7 +2062,7 @@
struct lysp_node *child_p, *dev_pnode = NULL, *dev_input_p = NULL, *dev_output_p = NULL;
struct lysp_action_inout *inout_p;
LY_ARRAY_COUNT_TYPE u;
- ly_bool not_supported;
+ ly_bool not_supported, enabled;
uint32_t opt_prev = ctx->options;
lysc_update_path(ctx, parent, action_p->name);
@@ -2046,7 +2071,8 @@
LY_CHECK_RET(lys_compile_node_deviations_refines(ctx, (struct lysp_node *)action_p, parent, &dev_pnode, ¬_supported));
if (not_supported) {
lysc_update_path(ctx, NULL, NULL);
- return LY_EDENIED;
+ ret = LY_EDENIED;
+ goto cleanup;
} else if (dev_pnode) {
action_p = (struct lysp_action *)dev_pnode;
}
@@ -2056,35 +2082,43 @@
action->module = ctx->cur_mod;
action->parent = parent;
- LY_CHECK_RET(lys_compile_node_uniqness(ctx, parent, action_p->name, (struct lysc_node *)action));
+ LY_CHECK_GOTO(ret = lys_compile_node_uniqness(ctx, parent, action_p->name, (struct lysc_node *)action), cleanup);
if (ctx->options & (LYS_COMPILE_RPC_MASK | LYS_COMPILE_NOTIFICATION)) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
"Action \"%s\" is placed inside %s.", action_p->name,
ctx->options & LYS_COMPILE_RPC_MASK ? "another RPC/action" : "notification");
- return LY_EVALID;
+ ret = LY_EVALID;
+ goto cleanup;
}
action->flags = action_p->flags & LYS_FLAGS_COMPILED_MASK;
+ /* if-features */
+ LY_CHECK_RET(lys_eval_iffeatures(ctx->ctx, action_p->iffeatures, &enabled));
+ if (!enabled && !(ctx->options & LYS_COMPILE_DISABLED)) {
+ ly_set_add(&ctx->disabled, action, 1, NULL);
+ ctx->options |= LYS_COMPILE_DISABLED;
+ }
+
/* status - it is not inherited by specification, but it does not make sense to have
* current in deprecated or deprecated in obsolete, so we do print warning and inherit status */
- LY_CHECK_RET(lys_compile_status(ctx, &action->flags, uses_status ? uses_status : (parent ? parent->flags : 0)));
+ ret = lys_compile_status(ctx, &action->flags, uses_status ? uses_status : (parent ? parent->flags : 0));
+ LY_CHECK_GOTO(ret, cleanup);
DUP_STRING_GOTO(ctx->ctx, action_p->name, action->name, ret, cleanup);
DUP_STRING_GOTO(ctx->ctx, action_p->dsc, action->dsc, ret, cleanup);
DUP_STRING_GOTO(ctx->ctx, action_p->ref, action->ref, ret, cleanup);
- COMPILE_ARRAY_GOTO(ctx, action_p->iffeatures, action->iffeatures, u, lys_compile_iffeature, ret, cleanup);
/* connect any action augments */
- LY_CHECK_RET(lys_compile_node_augments(ctx, (struct lysc_node *)action));
+ LY_CHECK_GOTO(ret = lys_compile_node_augments(ctx, (struct lysc_node *)action), cleanup);
/* input */
lysc_update_path(ctx, (struct lysc_node *)action, "input");
/* apply deviations on input */
- LY_CHECK_RET(lys_compile_node_deviations_refines(ctx, (struct lysp_node *)&action_p->input, (struct lysc_node *)action,
- &dev_input_p, ¬_supported));
+ LY_CHECK_GOTO(ret = lys_compile_node_deviations_refines(ctx, (struct lysp_node *)&action_p->input,
+ (struct lysc_node *)action, &dev_input_p, ¬_supported), cleanup);
if (not_supported) {
inout_p = NULL;
} else if (dev_input_p) {
@@ -2100,10 +2134,10 @@
ctx->options |= LYS_COMPILE_RPC_INPUT;
/* connect any input augments */
- LY_CHECK_RET(lys_compile_node_augments(ctx, (struct lysc_node *)&action->input));
+ LY_CHECK_GOTO(ret = lys_compile_node_augments(ctx, (struct lysc_node *)&action->input), cleanup);
LY_LIST_FOR(inout_p->data, child_p) {
- LY_CHECK_RET(lys_compile_node(ctx, child_p, (struct lysc_node *)action, uses_status, NULL));
+ LY_CHECK_GOTO(ret = lys_compile_node(ctx, child_p, (struct lysc_node *)action, uses_status, NULL), cleanup);
}
ctx->options = opt_prev;
}
@@ -2114,8 +2148,8 @@
lysc_update_path(ctx, (struct lysc_node *)action, "output");
/* apply deviations on output */
- LY_CHECK_RET(lys_compile_node_deviations_refines(ctx, (struct lysp_node *)&action_p->output, (struct lysc_node *)action,
- &dev_output_p, ¬_supported));
+ LY_CHECK_GOTO(ret = lys_compile_node_deviations_refines(ctx, (struct lysp_node *)&action_p->output,
+ (struct lysc_node *)action, &dev_output_p, ¬_supported), cleanup);
if (not_supported) {
inout_p = NULL;
} else if (dev_output_p) {
@@ -2131,10 +2165,10 @@
ctx->options |= LYS_COMPILE_RPC_OUTPUT;
/* connect any output augments */
- LY_CHECK_RET(lys_compile_node_augments(ctx, (struct lysc_node *)&action->output));
+ LY_CHECK_GOTO(ret = lys_compile_node_augments(ctx, (struct lysc_node *)&action->output), cleanup);
LY_LIST_FOR(inout_p->data, child_p) {
- LY_CHECK_RET(lys_compile_node(ctx, child_p, (struct lysc_node *)action, uses_status, NULL));
+ LY_CHECK_GOTO(ret = lys_compile_node(ctx, child_p, (struct lysc_node *)action, uses_status, NULL), cleanup);
}
ctx->options = opt_prev;
}
@@ -2144,7 +2178,7 @@
/* wait with extensions compilation until all the children are compiled */
COMPILE_EXTS_GOTO(ctx, action_p->exts, action->exts, action, LYEXT_PAR_NODE, ret, cleanup);
- if ((action->input.musts || action->output.musts) && !(ctx->options & LYS_COMPILE_GROUPING)) {
+ if ((action->input.musts || action->output.musts) && !(ctx->options & (LYS_COMPILE_DISABLED | LYS_COMPILE_GROUPING))) {
/* do not check "must" semantics in a grouping */
ret = ly_set_add(&ctx->xpath, action, 0, NULL);
LY_CHECK_GOTO(ret, cleanup);
@@ -2167,7 +2201,7 @@
LY_ERR ret = LY_SUCCESS;
struct lysp_node *child_p, *dev_pnode = NULL;
LY_ARRAY_COUNT_TYPE u;
- ly_bool not_supported;
+ ly_bool not_supported, enabled;
uint32_t opt_prev = ctx->options;
lysc_update_path(ctx, parent, notif_p->name);
@@ -2175,7 +2209,8 @@
LY_CHECK_RET(lys_compile_node_deviations_refines(ctx, (struct lysp_node *)notif_p, parent, &dev_pnode, ¬_supported));
if (not_supported) {
lysc_update_path(ctx, NULL, NULL);
- return LY_EDENIED;
+ ret = LY_EDENIED;
+ goto cleanup;
} else if (dev_pnode) {
notif_p = (struct lysp_notif *)dev_pnode;
}
@@ -2185,17 +2220,25 @@
notif->module = ctx->cur_mod;
notif->parent = parent;
- LY_CHECK_RET(lys_compile_node_uniqness(ctx, parent, notif_p->name, (struct lysc_node *)notif));
+ LY_CHECK_GOTO(ret = lys_compile_node_uniqness(ctx, parent, notif_p->name, (struct lysc_node *)notif), cleanup);
if (ctx->options & (LYS_COMPILE_RPC_MASK | LYS_COMPILE_NOTIFICATION)) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
"Notification \"%s\" is placed inside %s.", notif_p->name,
ctx->options & LYS_COMPILE_RPC_MASK ? "RPC/action" : "another notification");
- return LY_EVALID;
+ ret = LY_EVALID;
+ goto cleanup;
}
notif->flags = notif_p->flags & LYS_FLAGS_COMPILED_MASK;
+ /* if-features */
+ LY_CHECK_RET(lys_eval_iffeatures(ctx->ctx, notif_p->iffeatures, &enabled));
+ if (!enabled && !(ctx->options & LYS_COMPILE_DISABLED)) {
+ ly_set_add(&ctx->disabled, notif, 1, NULL);
+ ctx->options |= LYS_COMPILE_DISABLED;
+ }
+
/* status - it is not inherited by specification, but it does not make sense to have
* current in deprecated or deprecated in obsolete, so we do print warning and inherit status */
ret = lys_compile_status(ctx, ¬if->flags, uses_status ? uses_status : (parent ? parent->flags : 0));
@@ -2204,9 +2247,8 @@
DUP_STRING_GOTO(ctx->ctx, notif_p->name, notif->name, ret, cleanup);
DUP_STRING_GOTO(ctx->ctx, notif_p->dsc, notif->dsc, ret, cleanup);
DUP_STRING_GOTO(ctx->ctx, notif_p->ref, notif->ref, ret, cleanup);
- COMPILE_ARRAY_GOTO(ctx, notif_p->iffeatures, notif->iffeatures, u, lys_compile_iffeature, ret, cleanup);
COMPILE_ARRAY_GOTO(ctx, notif_p->musts, notif->musts, u, lys_compile_must, ret, cleanup);
- if (notif_p->musts && !(ctx->options & LYS_COMPILE_GROUPING)) {
+ if (notif_p->musts && !(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
/* do not check "must" semantics in a grouping */
ret = ly_set_add(&ctx->xpath, notif, 0, NULL);
LY_CHECK_GOTO(ret, cleanup);
@@ -2215,7 +2257,7 @@
ctx->options |= LYS_COMPILE_NOTIFICATION;
/* connect any notification augments */
- LY_CHECK_RET(lys_compile_node_augments(ctx, (struct lysc_node *)notif));
+ LY_CHECK_GOTO(ret = lys_compile_node_augments(ctx, (struct lysc_node *)notif), cleanup);
LY_LIST_FOR(notif_p->data, child_p) {
ret = lys_compile_node(ctx, child_p, (struct lysc_node *)notif, uses_status, NULL);
@@ -2287,7 +2329,7 @@
}
COMPILE_ARRAY_GOTO(ctx, cont_p->musts, cont->musts, u, lys_compile_must, ret, done);
- if (cont_p->musts && !(ctx->options & LYS_COMPILE_GROUPING)) {
+ if (cont_p->musts && !(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
/* do not check "must" semantics in a grouping */
ret = ly_set_add(&ctx->xpath, cont, 0, NULL);
LY_CHECK_GOTO(ret, done);
@@ -2321,10 +2363,10 @@
LY_CHECK_RET(lysc_unres_leaf_dflt_add(ctx, leaf, dflt));
}
- if (leaf->type->basetype == LY_TYPE_LEAFREF) {
+ if ((leaf->type->basetype == LY_TYPE_LEAFREF) && !(ctx->options & LYS_COMPILE_DISABLED)) {
/* store to validate the path in the current context at the end of schema compiling when all the nodes are present */
LY_CHECK_RET(ly_set_add(&ctx->leafrefs, leaf, 0, NULL));
- } else if (leaf->type->basetype == LY_TYPE_UNION) {
+ } else if ((leaf->type->basetype == LY_TYPE_UNION) && !(ctx->options & LYS_COMPILE_DISABLED)) {
LY_ARRAY_COUNT_TYPE u;
LY_ARRAY_FOR(((struct lysc_type_union *)leaf->type)->types, u) {
if (((struct lysc_type_union *)leaf->type)->types[u]->basetype == LY_TYPE_LEAFREF) {
@@ -2360,7 +2402,7 @@
LY_ERR ret = LY_SUCCESS;
COMPILE_ARRAY_GOTO(ctx, leaf_p->musts, leaf->musts, u, lys_compile_must, ret, done);
- if (leaf_p->musts && !(ctx->options & LYS_COMPILE_GROUPING)) {
+ if (leaf_p->musts && !(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
/* do not check "must" semantics in a grouping */
ret = ly_set_add(&ctx->xpath, leaf, 0, NULL);
LY_CHECK_GOTO(ret, done);
@@ -2408,7 +2450,7 @@
LY_ERR ret = LY_SUCCESS;
COMPILE_ARRAY_GOTO(ctx, llist_p->musts, llist->musts, u, lys_compile_must, ret, done);
- if (llist_p->musts && !(ctx->options & LYS_COMPILE_GROUPING)) {
+ if (llist_p->musts && !(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
/* do not check "must" semantics in a grouping */
ret = ly_set_add(&ctx->xpath, llist, 0, NULL);
LY_CHECK_GOTO(ret, done);
@@ -2550,7 +2592,7 @@
}
} else {
ctx_node = lys_find_child(ctx_node, mod, name, name_len, 0,
- getnext_extra_flag | LYS_GETNEXT_NOSTATECHECK | LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE);
+ getnext_extra_flag | LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE);
getnext_extra_flag = 0;
}
if (!ctx_node) {
@@ -2714,7 +2756,7 @@
}
COMPILE_ARRAY_GOTO(ctx, list_p->musts, list->musts, u, lys_compile_must, ret, done);
- if (list_p->musts && !(ctx->options & LYS_COMPILE_GROUPING)) {
+ if (list_p->musts && !(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
/* do not check "must" semantics in a grouping */
LY_CHECK_RET(ly_set_add(&ctx->xpath, list, 0, NULL));
}
@@ -2743,17 +2785,15 @@
}
/* key node must be present */
- key = (struct lysc_node_leaf *)lys_find_child(node, node->module, keystr, len, LYS_LEAF, LYS_GETNEXT_NOCHOICE | LYS_GETNEXT_NOSTATECHECK);
- if (!(key)) {
- LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
- "The list's key \"%.*s\" not found.", len, keystr);
+ key = (struct lysc_node_leaf *)lys_find_child(node, node->module, keystr, len, LYS_LEAF, LYS_GETNEXT_NOCHOICE);
+ if (!key) {
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, "The list's key \"%.*s\" not found.", len, keystr);
return LY_EVALID;
}
/* keys must be unique */
if (key->flags & LYS_KEY) {
/* the node was already marked as a key */
- LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
- "Duplicated key identifier \"%.*s\".", len, keystr);
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS, "Duplicated key identifier \"%.*s\".", len, keystr);
return LY_EVALID;
}
@@ -2777,11 +2817,7 @@
"List's key must not have any \"when\" statement.");
return LY_EVALID;
}
- if (key->iffeatures) {
- LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
- "List's key must not have any \"if-feature\" statement.");
- return LY_EVALID;
- }
+ /* TODO check key, it cannot have any if-features */
}
/* check status */
@@ -2898,7 +2934,7 @@
mod = node->module;
}
- ch->dflt = (struct lysc_node_case *)lys_find_child(node, mod, name, 0, LYS_CASE, LYS_GETNEXT_NOSTATECHECK | LYS_GETNEXT_WITHCASE);
+ ch->dflt = (struct lysc_node_case *)lys_find_child(node, mod, name, 0, LYS_CASE, LYS_GETNEXT_WITHCASE);
if (!ch->dflt) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
"Default case \"%s\" not found.", dflt->str);
@@ -3008,7 +3044,7 @@
LY_ERR ret = LY_SUCCESS;
COMPILE_ARRAY_GOTO(ctx, any_p->musts, any->musts, u, lys_compile_must, ret, done);
- if (any_p->musts && !(ctx->options & LYS_COMPILE_GROUPING)) {
+ if (any_p->musts && !(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
/* do not check "must" semantics in a grouping */
ret = ly_set_add(&ctx->xpath, any, 0, NULL);
LY_CHECK_GOTO(ret, done);
@@ -3511,7 +3547,7 @@
.parent = NULL, .next = NULL,
.prev = (struct lysc_node *)&fake_container,
.name = "fake",
- .dsc = NULL, .ref = NULL, .exts = NULL, .iffeatures = NULL, .when = NULL,
+ .dsc = NULL, .ref = NULL, .exts = NULL, .when = NULL,
.child = NULL, .musts = NULL, .actions = NULL, .notifs = NULL
};
@@ -3603,8 +3639,8 @@
LY_ERR ret = LY_SUCCESS;
struct lysc_node *node = NULL;
struct lysp_node *dev_pnode = NULL;
- LY_ARRAY_COUNT_TYPE u;
- ly_bool not_supported;
+ ly_bool not_supported, enabled;
+ uint32_t prev_opts = ctx->options;
LY_ERR (*node_compile_spec)(struct lysc_ctx *, struct lysp_node *, struct lysc_node *);
@@ -3657,12 +3693,11 @@
LY_CHECK_ERR_RET(!node, LOGMEM(ctx->ctx), LY_EMEM);
/* compile any deviations for this node */
- LY_CHECK_ERR_RET(ret = lys_compile_node_deviations_refines(ctx, pnode, parent, &dev_pnode, ¬_supported),
- free(node), ret);
+ LY_CHECK_ERR_GOTO(ret = lys_compile_node_deviations_refines(ctx, pnode, parent, &dev_pnode, ¬_supported),
+ free(node), cleanup);
if (not_supported) {
free(node);
- lysc_update_path(ctx, NULL, NULL);
- return LY_SUCCESS;
+ goto cleanup;
} else if (dev_pnode) {
pnode = dev_pnode;
}
@@ -3672,6 +3707,13 @@
node->prev = node;
node->flags = pnode->flags & LYS_FLAGS_COMPILED_MASK;
+ /* if-features */
+ LY_CHECK_ERR_RET(ret = lys_eval_iffeatures(ctx->ctx, pnode->iffeatures, &enabled), free(node), ret);
+ if (!enabled && !(ctx->options & LYS_COMPILE_DISABLED)) {
+ ly_set_add(&ctx->disabled, node, 1, NULL);
+ ctx->options |= LYS_COMPILE_DISABLED;
+ }
+
/* config */
ret = lys_compile_config(ctx, node, parent);
LY_CHECK_GOTO(ret, error);
@@ -3697,7 +3739,6 @@
DUP_STRING_GOTO(ctx->ctx, pnode->name, node->name, ret, error);
DUP_STRING_GOTO(ctx->ctx, pnode->dsc, node->dsc, ret, error);
DUP_STRING_GOTO(ctx->ctx, pnode->ref, node->ref, ret, error);
- COMPILE_ARRAY_GOTO(ctx, pnode->iffeatures, node->iffeatures, u, lys_compile_iffeature, ret, error);
/* insert into parent's children/compiled module (we can no longer free the node separately on error) */
LY_CHECK_GOTO(ret = lys_compile_node_connect(ctx, parent, node), cleanup);
@@ -3726,16 +3767,16 @@
LY_CHECK_GOTO(ret = ly_set_add(child_set, node, 1, NULL), cleanup);
}
- lysc_update_path(ctx, NULL, NULL);
- lysp_dev_node_free(ctx->ctx, dev_pnode);
- return LY_SUCCESS;
+ goto cleanup;
error:
- lysc_node_free(ctx->ctx, node);
+ lysc_node_free(ctx->ctx, node, 0);
cleanup:
- if (dev_pnode) {
+ ctx->options = prev_opts;
+ if (ret && dev_pnode) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_OTHER, "Compilation of a deviated and/or refined node failed.");
- lysp_dev_node_free(ctx->ctx, dev_pnode);
}
+ lysp_dev_node_free(ctx->ctx, dev_pnode);
+ lysc_update_path(ctx, NULL, NULL);
return ret;
}