schema compile CHANGE add context to must and definition module to when
To resolve XPath correctly, some additional information are needed
(valueable) in the compiled must/when statement structures.
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 9f7e470..847b8d4 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -1156,10 +1156,11 @@
* @brief YANG when-stmt
*/
struct lysc_when {
+ struct lys_module *module; /**< module where the must was defined */
struct lyxp_expr *cond; /**< XPath when condition */
+ struct lysc_node *context; /**< context node for evaluating the expression */
const char *dsc; /**< description */
const char *ref; /**< reference */
- struct lysc_node *context; /**< context node for evaluating the expression */
struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
uint32_t refcount; /**< reference counter since some of the when statements are shared among several nodes */
};
@@ -1247,6 +1248,7 @@
struct lysc_must {
struct lys_module *module; /**< module where the must was defined */
+ struct lysc_node *context; /**< context node for evaluating the expression */
struct lyxp_expr *cond; /**< XPath when condition */
const char *dsc; /**< description */
const char *ref; /**< reference */
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index 69f76cb..e827ca3 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -84,6 +84,18 @@
} \
}
+#define COMPILE_ARRAY_MUST_GOTO(CTX, ARRAY_P, ARRAY_C, ITER, PARENT, RET, GOTO) \
+ if (ARRAY_P) { \
+ LY_ARRAY_CREATE_GOTO((CTX)->ctx, ARRAY_C, LY_ARRAY_SIZE(ARRAY_P), RET, GOTO); \
+ size_t __array_offset = LY_ARRAY_SIZE(ARRAY_C); \
+ for (ITER = 0; ITER < LY_ARRAY_SIZE(ARRAY_P); ++ITER) { \
+ LY_ARRAY_INCREMENT(ARRAY_C); \
+ RET = lys_compile_must(CTX, &(ARRAY_P)[ITER], &(ARRAY_C)[ITER + __array_offset]); \
+ LY_CHECK_GOTO(RET != LY_SUCCESS, GOTO); \
+ (ARRAY_C)[ITER + __array_offset].context = lysc_xpath_context((struct lysc_node*)PARENT); \
+ } \
+ }
+
#define COMPILE_MEMBER_GOTO(CTX, MEMBER_P, MEMBER_C, FUNC, RET, GOTO) \
if (MEMBER_P) { \
MEMBER_C = calloc(1, sizeof *(MEMBER_C)); \
@@ -807,6 +819,7 @@
*when = calloc(1, sizeof **when);
(*when)->refcount = 1;
(*when)->cond = lyxp_expr_parse(ctx->ctx, when_p->cond);
+ (*when)->module = ctx->mod_def;
DUP_STRING(ctx->ctx, when_p->dsc, (*when)->dsc);
DUP_STRING(ctx->ctx, when_p->ref, (*when)->ref);
LY_CHECK_ERR_GOTO(!(*when)->cond, ret = ly_errcode(ctx->ctx), done);
@@ -3448,6 +3461,20 @@
return LY_EEXIST;
}
+/**
+ * @brief Get the XPath context node for the given schema node.
+ * @param[in] start The schema node where the XPath expression appears.
+ * @return The context node to evaluate XPath expression in given schema node.
+ * @return NULL in case the context node is the root node.
+ */
+static struct lysc_node *
+lysc_xpath_context(struct lysc_node *start)
+{
+ for (; start && !(start->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA | LYS_ACTION | LYS_NOTIF));
+ start = start->parent);
+ return start;
+}
+
static LY_ERR lys_compile_node(struct lysc_ctx *ctx, struct lysp_node *node_p, struct lysc_node *parent, uint16_t uses_status);
/**
@@ -3505,7 +3532,7 @@
/* input */
lysc_update_path(ctx, (struct lysc_node*)action, "input");
- COMPILE_ARRAY_GOTO(ctx, action_p->input.musts, action->input.musts, u, lys_compile_must, ret, cleanup);
+ COMPILE_ARRAY_MUST_GOTO(ctx, action_p->input.musts, action->input.musts, u, action, ret, cleanup);
COMPILE_EXTS_GOTO(ctx, action_p->input.exts, action->input_exts, &action->input, LYEXT_PAR_INPUT, ret, cleanup);
ctx->options |= LYSC_OPT_RPC_INPUT;
LY_LIST_FOR(action_p->input.data, child_p) {
@@ -3516,7 +3543,7 @@
/* output */
lysc_update_path(ctx, (struct lysc_node*)action, "output");
- COMPILE_ARRAY_GOTO(ctx, action_p->output.musts, action->output.musts, u, lys_compile_must, ret, cleanup);
+ COMPILE_ARRAY_MUST_GOTO(ctx, action_p->output.musts, action->output.musts, u, action, ret, cleanup);
COMPILE_EXTS_GOTO(ctx, action_p->output.exts, action->output_exts, &action->output, LYEXT_PAR_OUTPUT, ret, cleanup);
ctx->options |= LYSC_OPT_RPC_OUTPUT;
LY_LIST_FOR(action_p->output.data, child_p) {
@@ -3581,7 +3608,7 @@
DUP_STRING(ctx->ctx, notif_p->dsc, notif->dsc);
DUP_STRING(ctx->ctx, notif_p->ref, notif->ref);
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);
+ COMPILE_ARRAY_MUST_GOTO(ctx, notif_p->musts, notif->musts, u, notif, ret, cleanup);
COMPILE_EXTS_GOTO(ctx, notif_p->exts, notif->exts, notif, LYEXT_PAR_NODE, ret, cleanup);
ctx->options |= LYSC_OPT_NOTIFICATION;
@@ -3620,7 +3647,7 @@
LY_CHECK_RET(lys_compile_node(ctx, child_p, node, 0));
}
- COMPILE_ARRAY_GOTO(ctx, cont_p->musts, cont->musts, u, lys_compile_must, ret, done);
+ COMPILE_ARRAY_MUST_GOTO(ctx, cont_p->musts, cont->musts, u, node, ret, done);
COMPILE_ARRAY1_GOTO(ctx, cont_p->actions, cont->actions, node, u, lys_compile_action, 0, ret, done);
COMPILE_ARRAY1_GOTO(ctx, cont_p->notifs, cont->notifs, node, u, lys_compile_notif, 0, ret, done);
@@ -3701,7 +3728,7 @@
unsigned int u;
LY_ERR ret = LY_SUCCESS;
- COMPILE_ARRAY_GOTO(ctx, leaf_p->musts, leaf->musts, u, lys_compile_must, ret, done);
+ COMPILE_ARRAY_MUST_GOTO(ctx, leaf_p->musts, leaf->musts, u, node, ret, done);
if (leaf_p->units) {
leaf->units = lydict_insert(ctx->ctx, leaf_p->units, 0);
leaf->flags |= LYS_SET_UNITS;
@@ -3762,7 +3789,7 @@
unsigned int u, v;
LY_ERR ret = LY_SUCCESS;
- COMPILE_ARRAY_GOTO(ctx, llist_p->musts, llist->musts, u, lys_compile_must, ret, done);
+ COMPILE_ARRAY_MUST_GOTO(ctx, llist_p->musts, llist->musts, u, node, ret, done);
if (llist_p->units) {
llist->units = lydict_insert(ctx->ctx, llist_p->units, 0);
llist->flags |= LYS_SET_UNITS;
@@ -3943,7 +3970,7 @@
LY_CHECK_RET(lys_compile_node(ctx, child_p, node, 0));
}
- COMPILE_ARRAY_GOTO(ctx, list_p->musts, list->musts, u, lys_compile_must, ret, done);
+ COMPILE_ARRAY_MUST_GOTO(ctx, list_p->musts, list->musts, u, node, ret, done);
/* keys */
if ((list->flags & LYS_CONFIG_W) && (!list_p->key || !list_p->key[0])) {
@@ -4242,7 +4269,7 @@
unsigned int u;
LY_ERR ret = LY_SUCCESS;
- COMPILE_ARRAY_GOTO(ctx, any_p->musts, any->musts, u, lys_compile_must, ret, done);
+ COMPILE_ARRAY_MUST_GOTO(ctx, any_p->musts, any->musts, u, node, ret, done);
if (any->flags & LYS_CONFIG_W) {
LOGWRN(ctx->ctx, "Use of %s to define configuration data is not recommended.",
@@ -4297,20 +4324,6 @@
}
/**
- * @brief Get the XPath context node for the given schema node.
- * @param[in] start The schema node where the XPath expression appears.
- * @return The context node to evaluate XPath expression in given schema node.
- * @return NULL in case the context node is the root node.
- */
-static struct lysc_node *
-lysc_xpath_context(struct lysc_node *start)
-{
- for (; start && !(start->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA | LYS_ACTION | LYS_NOTIF));
- start = start->parent);
- return start;
-}
-
-/**
* @brief Prepare the case structure in choice node for the new data node.
*
* It is able to handle implicit as well as explicit cases and the situation when the case has multiple data nodes and the case was already
@@ -5146,20 +5159,20 @@
if (rfn->musts) {
switch (node->nodetype) {
case LYS_LEAF:
- COMPILE_ARRAY_GOTO(ctx, rfn->musts, ((struct lysc_node_leaf*)node)->musts, u, lys_compile_must, ret, cleanup);
+ COMPILE_ARRAY_MUST_GOTO(ctx, rfn->musts, ((struct lysc_node_leaf*)node)->musts, u, node, ret, cleanup);
break;
case LYS_LEAFLIST:
- COMPILE_ARRAY_GOTO(ctx, rfn->musts, ((struct lysc_node_leaflist*)node)->musts, u, lys_compile_must, ret, cleanup);
+ COMPILE_ARRAY_MUST_GOTO(ctx, rfn->musts, ((struct lysc_node_leaflist*)node)->musts, u, node, ret, cleanup);
break;
case LYS_LIST:
- COMPILE_ARRAY_GOTO(ctx, rfn->musts, ((struct lysc_node_list*)node)->musts, u, lys_compile_must, ret, cleanup);
+ COMPILE_ARRAY_MUST_GOTO(ctx, rfn->musts, ((struct lysc_node_list*)node)->musts, u, node, ret, cleanup);
break;
case LYS_CONTAINER:
- COMPILE_ARRAY_GOTO(ctx, rfn->musts, ((struct lysc_node_container*)node)->musts, u, lys_compile_must, ret, cleanup);
+ COMPILE_ARRAY_MUST_GOTO(ctx, rfn->musts, ((struct lysc_node_container*)node)->musts, u, node, ret, cleanup);
break;
case LYS_ANYXML:
case LYS_ANYDATA:
- COMPILE_ARRAY_GOTO(ctx, rfn->musts, ((struct lysc_node_anydata*)node)->musts, u, lys_compile_must, ret, cleanup);
+ COMPILE_ARRAY_MUST_GOTO(ctx, rfn->musts, ((struct lysc_node_anydata*)node)->musts, u, node, ret, cleanup);
break;
default:
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
@@ -5947,27 +5960,27 @@
switch (devs[u]->target->nodetype) {
case LYS_CONTAINER:
case LYS_LIST:
- COMPILE_ARRAY_GOTO(ctx, d_add->musts, ((struct lysc_node_container*)devs[u]->target)->musts,
- x, lys_compile_must, ret, cleanup);
+ COMPILE_ARRAY_MUST_GOTO(ctx, d_add->musts, ((struct lysc_node_container*)devs[u]->target)->musts,
+ x, devs[u]->target, ret, cleanup);
break;
case LYS_LEAF:
case LYS_LEAFLIST:
case LYS_ANYDATA:
- COMPILE_ARRAY_GOTO(ctx, d_add->musts, ((struct lysc_node_leaf*)devs[u]->target)->musts,
- x, lys_compile_must, ret, cleanup);
+ COMPILE_ARRAY_MUST_GOTO(ctx, d_add->musts, ((struct lysc_node_leaf*)devs[u]->target)->musts,
+ x, devs[u]->target, ret, cleanup);
break;
case LYS_NOTIF:
- COMPILE_ARRAY_GOTO(ctx, d_add->musts, ((struct lysc_notif*)devs[u]->target)->musts,
- x, lys_compile_must, ret, cleanup);
+ COMPILE_ARRAY_MUST_GOTO(ctx, d_add->musts, ((struct lysc_notif*)devs[u]->target)->musts,
+ x, devs[u]->target, ret, cleanup);
break;
case LYS_ACTION:
if (devs[u]->flags & LYSC_OPT_RPC_INPUT) {
- COMPILE_ARRAY_GOTO(ctx, d_add->musts, ((struct lysc_action*)devs[u]->target)->input.musts,
- x, lys_compile_must, ret, cleanup);
+ COMPILE_ARRAY_MUST_GOTO(ctx, d_add->musts, ((struct lysc_action*)devs[u]->target)->input.musts,
+ x, devs[u]->target, ret, cleanup);
break;
} else if (devs[u]->flags & LYSC_OPT_RPC_OUTPUT) {
- COMPILE_ARRAY_GOTO(ctx, d_add->musts, ((struct lysc_action*)devs[u]->target)->output.musts,
- x, lys_compile_must, ret, cleanup);
+ COMPILE_ARRAY_MUST_GOTO(ctx, d_add->musts, ((struct lysc_action*)devs[u]->target)->output.musts,
+ x, devs[u]->target, ret, cleanup);
break;
}
/* fall through */