schema CHANGE unify actions, inouts and notification with lys*_node
diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c
index fb2c96f..7ea1ac5 100644
--- a/src/schema_compile_node.c
+++ b/src/schema_compile_node.c
@@ -258,9 +258,9 @@
/* get the when array */
if (node->nodetype & LYS_ACTION) {
- node_when = &((struct lysc_action *)node)->when;
+ node_when = &((struct lysc_node_action *)node)->when;
} else if (node->nodetype == LYS_NOTIF) {
- node_when = &((struct lysc_notif *)node)->when;
+ node_when = &((struct lysc_node_notif *)node)->when;
} else {
node_when = &node->when;
}
@@ -2007,10 +2007,9 @@
const struct lysc_node *exclude)
{
const struct lysc_node *iter, *iter2;
- const struct lysc_action *actions;
- const struct lysc_notif *notifs;
+ const struct lysc_node_action *actions;
+ const struct lysc_node_notif *notifs;
uint32_t getnext_flags;
- LY_ARRAY_COUNT_TYPE u;
#define CHECK_NODE(iter, exclude, name) (iter != (void *)exclude && (iter)->module == exclude->module && !strcmp(name, (iter)->name))
@@ -2058,15 +2057,15 @@
}
actions = parent ? lysc_node_actions(parent) : ctx->cur_mod->compiled->rpcs;
- LY_ARRAY_FOR(actions, u) {
- if (CHECK_NODE(&actions[u], exclude, name)) {
+ LY_LIST_FOR((struct lysc_node *)actions, iter) {
+ if (CHECK_NODE(iter, exclude, name)) {
goto error;
}
}
notifs = parent ? lysc_node_notifs(parent) : ctx->cur_mod->compiled->notifs;
- LY_ARRAY_FOR(notifs, u) {
- if (CHECK_NODE(¬ifs[u], exclude, name)) {
+ LY_LIST_FOR((struct lysc_node *)notifs, iter) {
+ if (CHECK_NODE(iter, exclude, name)) {
goto error;
}
}
@@ -2079,222 +2078,407 @@
#undef CHECK_NODE
}
-LY_ERR
-lys_compile_action(struct lysc_ctx *ctx, struct lysp_action *action_p, struct lysc_node *parent,
- struct lysc_action *action, uint16_t uses_status)
+/**
+ * @brief Connect the node into the siblings list and check its name uniqueness. Also,
+ * keep specific order of augments targetting the same node.
+ *
+ * @param[in] ctx Compile context
+ * @param[in] parent Parent node holding the children list, in case of node from a choice's case,
+ * the choice itself is expected instead of a specific case node.
+ * @param[in] node Schema node to connect into the list.
+ * @return LY_ERR value - LY_SUCCESS or LY_EEXIST.
+ * In case of LY_EEXIST, the node is actually kept in the tree, so do not free it directly.
+ */
+static LY_ERR
+lys_compile_node_connect(struct lysc_ctx *ctx, struct lysc_node *parent, struct lysc_node *node)
{
- LY_ERR ret = LY_SUCCESS;
- struct lysp_node *child_p, *dev_pnode = NULL, *dev_input_p = NULL, *dev_output_p = NULL;
- struct lysp_action_inout *inout_p;
- ly_bool not_supported, enabled;
- uint32_t opt_prev = ctx->options;
+ struct lysc_node **children, *anchor = NULL;
+ int insert_after = 0;
- lysc_update_path(ctx, parent, action_p->name);
+ node->parent = parent;
- /* apply deviation on the action/RPC */
- 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);
- ret = LY_EDENIED;
- goto cleanup;
- } else if (dev_pnode) {
- action_p = (struct lysp_action *)dev_pnode;
+ if (parent) {
+ if (parent->nodetype == LYS_CHOICE) {
+ assert(node->nodetype == LYS_CASE);
+ children = (struct lysc_node **)&((struct lysc_node_choice *)parent)->cases;
+ } else if (parent->nodetype & (LYS_ACTION | LYS_RPC)) {
+ assert(node->nodetype & (LYS_INPUT | LYS_OUTPUT));
+ /* inout nodes are part of the action and nothing more than setting the parent pointer is necessary */
+ return LY_SUCCESS;
+ } else if (node->nodetype == LYS_ACTION) {
+ children = (struct lysc_node **)lysc_node_actions_p(parent);
+ } else if (node->nodetype == LYS_NOTIF) {
+ children = (struct lysc_node **)lysc_node_notifs_p(parent);
+ } else {
+ children = lysc_node_children_p(parent, ctx->options);
+ }
+ assert(children);
+
+ if (!(*children)) {
+ /* first child */
+ *children = node;
+ } else if (node->flags & LYS_KEY) {
+ /* special handling of adding keys */
+ assert(node->module == parent->module);
+ anchor = *children;
+ if (anchor->flags & LYS_KEY) {
+ while ((anchor->flags & LYS_KEY) && anchor->next) {
+ anchor = anchor->next;
+ }
+ /* insert after the last key */
+ insert_after = 1;
+ } /* else insert before anchor (at the beginning) */
+ } else if ((*children)->prev->module == node->module) {
+ /* last child is from the same module, keep the order and insert at the end */
+ anchor = (*children)->prev;
+ insert_after = 1;
+ } else if (parent->module == node->module) {
+ /* adding module child after some augments were connected */
+ for (anchor = *children; anchor->module == node->module; anchor = anchor->next) {}
+ } else {
+ /* some augments are already connected and we are connecting new ones,
+ * keep module name order and insert the node into the children list */
+ anchor = *children;
+ do {
+ anchor = anchor->prev;
+
+ /* check that we have not found the last augment node from our module or
+ * the first augment node from a "smaller" module or
+ * the first node from a local module */
+ if ((anchor->module == node->module) || (strcmp(anchor->module->name, node->module->name) < 0) ||
+ (anchor->module == parent->module)) {
+ /* insert after */
+ insert_after = 1;
+ break;
+ }
+
+ /* we have traversed all the nodes, insert before anchor (as the first node) */
+ } while (anchor->prev->next);
+ }
+
+ /* insert */
+ if (anchor) {
+ if (insert_after) {
+ node->next = anchor->next;
+ node->prev = anchor;
+ anchor->next = node;
+ if (node->next) {
+ /* middle node */
+ node->next->prev = node;
+ } else {
+ /* last node */
+ (*children)->prev = node;
+ }
+ } else {
+ node->next = anchor;
+ node->prev = anchor->prev;
+ anchor->prev = node;
+ if (anchor == *children) {
+ /* first node */
+ *children = node;
+ } else {
+ /* middle node */
+ node->prev->next = node;
+ }
+ }
+ }
+
+ /* check the name uniqueness (even for an only child, it may be in case) */
+ if (lys_compile_node_uniqness(ctx, parent, node->name, node)) {
+ return LY_EEXIST;
+ }
+ } else {
+ /* top-level element */
+ struct lysc_node **list;
+
+ if (node->nodetype == LYS_RPC) {
+ list = (struct lysc_node **)&ctx->cur_mod->compiled->rpcs;
+ } else if (node->nodetype == LYS_NOTIF) {
+ list = (struct lysc_node **)&ctx->cur_mod->compiled->notifs;
+ } else {
+ list = &ctx->cur_mod->compiled->data;
+ }
+ if (!(*list)) {
+ *list = node;
+ } else {
+ /* insert at the end of the module's top-level nodes list */
+ (*list)->prev->next = node;
+ node->prev = (*list)->prev;
+ (*list)->prev = node;
+ }
+
+ /* check the name uniqueness on top-level */
+ if (lys_compile_node_uniqness(ctx, NULL, node->name, node)) {
+ return LY_EEXIST;
+ }
}
- /* member needed for uniqueness check lys_getnext() */
- action->nodetype = parent ? LYS_ACTION : LYS_RPC;
- action->module = ctx->cur_mod;
- action->parent = parent;
+ return LY_SUCCESS;
+}
- LY_CHECK_GOTO(ret = lys_compile_node_uniqness(ctx, parent, action_p->name, (struct lysc_node *)action), cleanup);
+/**
+ * @brief Set config flags for a node.
+ *
+ * @param[in] ctx Compile context.
+ * @param[in] node Compiled node config to set.
+ * @param[in] parent Parent of @p node.
+ * @return LY_ERR value.
+ */
+static LY_ERR
+lys_compile_config(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc_node *parent)
+{
+ /* case never has any explicit config */
+ assert((node->nodetype != LYS_CASE) || !(node->flags & LYS_CONFIG_MASK));
- if (ctx->options & (LYS_COMPILE_RPC_MASK | LYS_COMPILE_NOTIFICATION)) {
+ if (node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)) {
+ /* no config inheritance, config flag is set by copying flags from parsed node */
+ return LY_SUCCESS;
+ } else if (ctx->options & (LYS_COMPILE_RPC_INPUT | LYS_COMPILE_RPC_OUTPUT)) {
+ /* ignore config statements inside RPC/action data */
+ node->flags &= ~LYS_CONFIG_MASK;
+ node->flags |= (ctx->options & LYS_COMPILE_RPC_INPUT) ? LYS_CONFIG_W : LYS_CONFIG_R;
+ } else if (ctx->options & LYS_COMPILE_NOTIFICATION) {
+ /* ignore config statements inside Notification data */
+ node->flags &= ~LYS_CONFIG_MASK;
+ node->flags |= LYS_CONFIG_R;
+ } else if (!(node->flags & LYS_CONFIG_MASK)) {
+ /* config not explicitly set, inherit it from parent */
+ if (parent) {
+ node->flags |= parent->flags & LYS_CONFIG_MASK;
+ } else {
+ /* default is config true */
+ node->flags |= LYS_CONFIG_W;
+ }
+ } else {
+ /* config set explicitly */
+ node->flags |= LYS_SET_CONFIG;
+ }
+
+ if (parent && (parent->flags & LYS_CONFIG_R) && (node->flags & LYS_CONFIG_W)) {
LOGVAL(ctx->ctx, LYVE_SEMANTICS,
- "Action \"%s\" is placed inside %s.", action_p->name,
- ctx->options & LYS_COMPILE_RPC_MASK ? "another RPC/action" : "notification");
- ret = LY_EVALID;
- goto cleanup;
+ "Configuration node cannot be child of any state data node.");
+ return LY_EVALID;
}
- 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 | LYS_COMPILE_GROUPING))) {
- 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 */
- 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);
-
- /* connect any action augments */
- 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_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) {
- inout_p = (struct lysp_action_inout *)dev_input_p;
- } else {
- inout_p = &action_p->input;
- }
-
- if (inout_p) {
- action->input.nodetype = LYS_INPUT;
- COMPILE_ARRAY_GOTO(ctx, inout_p->musts, action->input.musts, lys_compile_must, ret, cleanup);
- COMPILE_EXTS_GOTO(ctx, inout_p->exts, action->input_exts, &action->input, LYEXT_PAR_INPUT, ret, cleanup);
- ctx->options |= LYS_COMPILE_RPC_INPUT;
-
- /* connect any input augments */
- 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_GOTO(ret = lys_compile_node(ctx, child_p, (struct lysc_node *)action, uses_status, NULL), cleanup);
- }
- ctx->options = opt_prev;
- }
-
- lysc_update_path(ctx, NULL, NULL);
-
- /* output */
- lysc_update_path(ctx, (struct lysc_node *)action, "output");
-
- /* apply deviations on output */
- 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) {
- inout_p = (struct lysp_action_inout *)dev_output_p;
- } else {
- inout_p = &action_p->output;
- }
-
- if (inout_p) {
- action->output.nodetype = LYS_OUTPUT;
- COMPILE_ARRAY_GOTO(ctx, inout_p->musts, action->output.musts, lys_compile_must, ret, cleanup);
- COMPILE_EXTS_GOTO(ctx, inout_p->exts, action->output_exts, &action->output, LYEXT_PAR_OUTPUT, ret, cleanup);
- ctx->options |= LYS_COMPILE_RPC_OUTPUT;
-
- /* connect any output augments */
- 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_GOTO(ret = lys_compile_node(ctx, child_p, (struct lysc_node *)action, uses_status, NULL), cleanup);
- }
- ctx->options = opt_prev;
- }
-
- lysc_update_path(ctx, NULL, NULL);
-
- /* 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_DISABLED | LYS_COMPILE_GROUPING))) {
- /* do not check "must" semantics in a grouping */
- ret = ly_set_add(&ctx->unres->xpath, action, 0, NULL);
- LY_CHECK_GOTO(ret, cleanup);
- }
-
- lysc_update_path(ctx, NULL, NULL);
-
-cleanup:
- lysp_dev_node_free(ctx->ctx, dev_pnode);
- lysp_dev_node_free(ctx->ctx, dev_input_p);
- lysp_dev_node_free(ctx->ctx, dev_output_p);
- ctx->options = opt_prev;
- return ret;
+ return LY_SUCCESS;
}
LY_ERR
-lys_compile_notif(struct lysc_ctx *ctx, struct lysp_notif *notif_p, struct lysc_node *parent, struct lysc_notif *notif,
- uint16_t uses_status)
+lys_compile_node_(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *parent, uint16_t uses_status,
+ LY_ERR (*node_compile_spec)(struct lysc_ctx *, struct lysp_node *, struct lysc_node *),
+ struct lysc_node *node, struct ly_set *child_set)
{
LY_ERR ret = LY_SUCCESS;
- struct lysp_node *child_p, *dev_pnode = NULL;
ly_bool not_supported, enabled;
- uint32_t opt_prev = ctx->options;
+ struct lysp_node *dev_pnode = NULL;
- lysc_update_path(ctx, parent, notif_p->name);
+ node->nodetype = pnode->nodetype;
+ node->module = ctx->cur_mod;
+ node->prev = node;
- LY_CHECK_RET(lys_compile_node_deviations_refines(ctx, (struct lysp_node *)notif_p, parent, &dev_pnode, ¬_supported));
+ /* compile any deviations for this node */
+ LY_CHECK_GOTO(ret = lys_compile_node_deviations_refines(ctx, pnode, parent, &dev_pnode, ¬_supported), error);
if (not_supported) {
- lysc_update_path(ctx, NULL, NULL);
- ret = LY_EDENIED;
- goto cleanup;
+ goto error;
} else if (dev_pnode) {
- notif_p = (struct lysp_notif *)dev_pnode;
+ pnode = dev_pnode;
}
- /* member needed for uniqueness check lys_getnext() */
- notif->nodetype = LYS_NOTIF;
- notif->module = ctx->cur_mod;
- notif->parent = parent;
-
- 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, LYVE_SEMANTICS,
- "Notification \"%s\" is placed inside %s.", notif_p->name,
- ctx->options & LYS_COMPILE_RPC_MASK ? "RPC/action" : "another notification");
- ret = LY_EVALID;
- goto cleanup;
- }
-
- notif->flags = notif_p->flags & LYS_FLAGS_COMPILED_MASK;
+ node->flags = pnode->flags & LYS_FLAGS_COMPILED_MASK;
/* if-features */
- LY_CHECK_RET(lys_eval_iffeatures(ctx->ctx, notif_p->iffeatures, &enabled));
+ LY_CHECK_GOTO(ret = lys_eval_iffeatures(ctx->ctx, pnode->iffeatures, &enabled), error);
if (!enabled && !(ctx->options & (LYS_COMPILE_DISABLED | LYS_COMPILE_GROUPING))) {
- ly_set_add(&ctx->disabled, notif, 1, NULL);
+ 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);
+
+ /* list ordering */
+ if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
+ if ((node->flags & LYS_CONFIG_R) && (node->flags & LYS_ORDBY_MASK)) {
+ LOGWRN(ctx->ctx, "The ordered-by statement is ignored in lists representing %s (%s).",
+ (ctx->options & LYS_COMPILE_RPC_OUTPUT) ? "RPC/action output parameters" :
+ (ctx->options & LYS_COMPILE_NOTIFICATION) ? "notification content" : "state data", ctx->path);
+ node->flags &= ~LYS_ORDBY_MASK;
+ node->flags |= LYS_ORDBY_SYSTEM;
+ } else if (!(node->flags & LYS_ORDBY_MASK)) {
+ /* default ordering is system */
+ node->flags |= LYS_ORDBY_SYSTEM;
+ }
+ }
+
/* 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));
- LY_CHECK_GOTO(ret, cleanup);
+ LY_CHECK_GOTO(ret = lys_compile_status(ctx, &node->flags, uses_status ? uses_status : (parent ? parent->flags : 0)), error);
- 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->musts, notif->musts, lys_compile_must, ret, cleanup);
+ 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);
+
+ /* 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);
+
+ if (pnode->when) {
+ /* compile when */
+ ret = lys_compile_when(ctx, pnode->when, pnode->flags, lysc_data_node(node), node, NULL);
+ LY_CHECK_GOTO(ret, cleanup);
+ }
+
+ /* connect any augments */
+ LY_CHECK_GOTO(ret = lys_compile_node_augments(ctx, node), cleanup);
+
+ /* nodetype-specific part */
+ LY_CHECK_GOTO(ret = node_compile_spec(ctx, pnode, node), cleanup);
+
+ /* final compilation tasks that require the node to be connected */
+ COMPILE_EXTS_GOTO(ctx, pnode->exts, node->exts, node, LYEXT_PAR_NODE, ret, cleanup);
+ if (node->flags & LYS_MAND_TRUE) {
+ /* inherit LYS_MAND_TRUE in parent containers */
+ lys_compile_mandatory_parents(parent, 1);
+ }
+
+ if (child_set) {
+ /* add the new node into set */
+ LY_CHECK_GOTO(ret = ly_set_add(child_set, node, 1, NULL), cleanup);
+ }
+
+ goto cleanup;
+
+error:
+ lysc_node_free(ctx->ctx, node, 0);
+cleanup:
+ if (ret && dev_pnode) {
+ LOGVAL(ctx->ctx, LYVE_OTHER, "Compilation of a deviated and/or refined node failed.");
+ }
+ lysp_dev_node_free(ctx->ctx, dev_pnode);
+ return ret;
+}
+
+/**
+ * @brief Compile parsed action's input/output node information.
+ * @param[in] ctx Compile context
+ * @param[in] pnode Parsed inout node.
+ * @param[in,out] node Pre-prepared structure from lys_compile_node_() with filled generic node information
+ * is enriched with the inout-specific information.
+ * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
+ */
+LY_ERR
+lys_compile_node_action_inout(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
+{
+ LY_ERR ret = LY_SUCCESS;
+ struct lysp_node *child_p;
+ uint32_t prev_options = ctx->options;
+
+ struct lysp_node_action_inout *inout_p = (struct lysp_node_action_inout *)pnode;
+ struct lysc_node_action_inout *inout = (struct lysc_node_action_inout *)node;
+
+ COMPILE_ARRAY_GOTO(ctx, inout_p->musts, inout->musts, lys_compile_must, ret, done);
+ COMPILE_EXTS_GOTO(ctx, inout_p->exts, inout->exts, inout, inout_p->nodetype == LYS_INPUT ? LYEXT_PAR_INPUT : LYEXT_PAR_OUTPUT,
+ ret, done);
+ ctx->options |= inout_p->nodetype == LYS_INPUT ? LYS_COMPILE_RPC_INPUT : LYS_COMPILE_RPC_OUTPUT;
+
+ LY_LIST_FOR(inout_p->data, child_p) {
+ LY_CHECK_GOTO(ret = lys_compile_node(ctx, child_p, node, 0, NULL), done);
+ }
+
+ ctx->options = prev_options;
+
+done:
+ return ret;
+}
+
+/**
+ * @brief Compile parsed action node information.
+ * @param[in] ctx Compile context
+ * @param[in] pnode Parsed action node.
+ * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
+ * is enriched with the action-specific information.
+ * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
+ */
+LY_ERR
+lys_compile_node_action(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
+{
+ LY_ERR ret;
+ struct lysp_node_action *action_p = (struct lysp_node_action *)pnode;
+ struct lysc_node_action *action = (struct lysc_node_action *)node;
+ struct lysp_node_action_inout *input, implicit_input = {
+ .nodetype = LYS_INPUT,
+ .name = "input",
+ .parent = pnode,
+ };
+ struct lysp_node_action_inout *output, implicit_output = {
+ .nodetype = LYS_OUTPUT,
+ .name = "output",
+ .parent = pnode,
+ };
+
+ /* output */
+ lysc_update_path(ctx, (struct lysc_node *)action, "input");
+ if (action_p->input.nodetype == LYS_UNKNOWN) {
+ input = &implicit_input;
+ } else {
+ input = &action_p->input;
+ }
+ ret = lys_compile_node_(ctx, (struct lysp_node *)input, (struct lysc_node *)action, 0,
+ lys_compile_node_action_inout, (struct lysc_node *)&action->input, NULL);
+ lysc_update_path(ctx, NULL, NULL);
+ LY_CHECK_GOTO(ret, done);
+
+ /* output */
+ lysc_update_path(ctx, (struct lysc_node *)action, "output");
+ if (action_p->input.nodetype == LYS_UNKNOWN) {
+ output = &implicit_output;
+ } else {
+ output = &action_p->output;
+ }
+ ret = lys_compile_node_(ctx, (struct lysp_node *)output, (struct lysc_node *)action, 0,
+ lys_compile_node_action_inout, (struct lysc_node *)&action->output, NULL);
+ lysc_update_path(ctx, NULL, NULL);
+ LY_CHECK_GOTO(ret, done);
+
+ /* do not check "must" semantics in a grouping */
+ if ((action->input.musts || action->output.musts) && !(ctx->options & (LYS_COMPILE_DISABLED | LYS_COMPILE_GROUPING))) {
+ ret = ly_set_add(&ctx->unres->xpath, action, 0, NULL);
+ LY_CHECK_GOTO(ret, done);
+ }
+
+done:
+ return ret;
+}
+
+/**
+ * @brief Compile parsed action node information.
+ * @param[in] ctx Compile context
+ * @param[in] pnode Parsed action node.
+ * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
+ * is enriched with the action-specific information.
+ * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
+ */
+LY_ERR
+lys_compile_node_notif(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
+{
+ LY_ERR ret = LY_SUCCESS;
+ struct lysp_node_notif *notif_p = (struct lysp_node_notif *)pnode;
+ struct lysc_node_notif *notif = (struct lysc_node_notif *)node;
+ struct lysp_node *child_p;
+
+ COMPILE_ARRAY_GOTO(ctx, notif_p->musts, notif->musts, lys_compile_must, ret, done);
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->unres->xpath, notif, 0, NULL);
- LY_CHECK_GOTO(ret, cleanup);
+ LY_CHECK_GOTO(ret, done);
}
- ctx->options |= LYS_COMPILE_NOTIFICATION;
-
- /* connect any notification augments */
- 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);
- LY_CHECK_GOTO(ret, cleanup);
+ ret = lys_compile_node(ctx, child_p, (struct lysc_node *)notif, 0, NULL);
+ LY_CHECK_GOTO(ret, done);
}
- /* wait with extension compilation until all the children are compiled */
- COMPILE_EXTS_GOTO(ctx, notif_p->exts, notif->exts, notif, LYEXT_PAR_NODE, ret, cleanup);
-
- lysc_update_path(ctx, NULL, NULL);
-
-cleanup:
- lysp_dev_node_free(ctx->ctx, dev_pnode);
- ctx->options = opt_prev;
+done:
return ret;
}
@@ -2358,8 +2542,15 @@
ret = ly_set_add(&ctx->unres->xpath, cont, 0, NULL);
LY_CHECK_GOTO(ret, done);
}
- COMPILE_OP_ARRAY_GOTO(ctx, cont_p->actions, cont->actions, node, lys_compile_action, 0, ret, done);
- COMPILE_OP_ARRAY_GOTO(ctx, cont_p->notifs, cont->notifs, node, lys_compile_notif, 0, ret, done);
+
+ LY_LIST_FOR((struct lysp_node *)cont_p->actions, child_p) {
+ ret = lys_compile_node(ctx, child_p, node, 0, NULL);
+ LY_CHECK_GOTO(ret, done);
+ }
+ LY_LIST_FOR((struct lysp_node *)cont_p->notifs, child_p) {
+ ret = lys_compile_node(ctx, child_p, node, 0, NULL);
+ LY_CHECK_GOTO(ret, done);
+ }
done:
return ret;
@@ -2603,9 +2794,9 @@
return LY_ENOTFOUND;
}
if (!ly_strncmp("input", name, name_len)) {
- ctx_node = (struct lysc_node *)&((struct lysc_action *)ctx_node)->input;
+ ctx_node = (struct lysc_node *)&((struct lysc_node_action *)ctx_node)->input;
} else if (!ly_strncmp("output", name, name_len)) {
- ctx_node = (struct lysc_node *)&((struct lysc_action *)ctx_node)->output;
+ ctx_node = (struct lysc_node *)&((struct lysc_node_action *)ctx_node)->output;
getnext_extra_flag = LYS_GETNEXT_OUTPUT;
} else {
/* only input or output is valid */
@@ -2902,8 +3093,14 @@
LY_CHECK_RET(lys_compile_node_list_unique(ctx, list_p->uniques, list));
}
- COMPILE_OP_ARRAY_GOTO(ctx, list_p->actions, list->actions, node, lys_compile_action, 0, ret, done);
- COMPILE_OP_ARRAY_GOTO(ctx, list_p->notifs, list->notifs, node, lys_compile_notif, 0, ret, done);
+ LY_LIST_FOR((struct lysp_node *)list_p->actions, child_p) {
+ ret = lys_compile_node(ctx, child_p, node, 0, NULL);
+ LY_CHECK_GOTO(ret, done);
+ }
+ LY_LIST_FOR((struct lysp_node *)list_p->notifs, child_p) {
+ ret = lys_compile_node(ctx, child_p, node, 0, NULL);
+ LY_CHECK_GOTO(ret, done);
+ }
/* checks */
if (list->min > list->max) {
@@ -3078,127 +3275,6 @@
}
/**
- * @brief Connect the node into the siblings list and check its name uniqueness. Also,
- * keep specific order of augments targetting the same node.
- *
- * @param[in] ctx Compile context
- * @param[in] parent Parent node holding the children list, in case of node from a choice's case,
- * the choice itself is expected instead of a specific case node.
- * @param[in] node Schema node to connect into the list.
- * @return LY_ERR value - LY_SUCCESS or LY_EEXIST.
- * In case of LY_EEXIST, the node is actually kept in the tree, so do not free it directly.
- */
-static LY_ERR
-lys_compile_node_connect(struct lysc_ctx *ctx, struct lysc_node *parent, struct lysc_node *node)
-{
- struct lysc_node **children, *anchor = NULL;
- int insert_after = 0;
-
- node->parent = parent;
-
- if (parent) {
- if (parent->nodetype == LYS_CHOICE) {
- assert(node->nodetype == LYS_CASE);
- children = (struct lysc_node **)&((struct lysc_node_choice *)parent)->cases;
- } else {
- children = lysc_node_children_p(parent, ctx->options);
- }
- assert(children);
-
- if (!(*children)) {
- /* first child */
- *children = node;
- } else if (node->flags & LYS_KEY) {
- /* special handling of adding keys */
- assert(node->module == parent->module);
- anchor = *children;
- if (anchor->flags & LYS_KEY) {
- while ((anchor->flags & LYS_KEY) && anchor->next) {
- anchor = anchor->next;
- }
- /* insert after the last key */
- insert_after = 1;
- } /* else insert before anchor (at the beginning) */
- } else if ((*children)->prev->module == node->module) {
- /* last child is from the same module, keep the order and insert at the end */
- anchor = (*children)->prev;
- insert_after = 1;
- } else if (parent->module == node->module) {
- /* adding module child after some augments were connected */
- for (anchor = *children; anchor->module == node->module; anchor = anchor->next) {}
- } else {
- /* some augments are already connected and we are connecting new ones,
- * keep module name order and insert the node into the children list */
- anchor = *children;
- do {
- anchor = anchor->prev;
-
- /* check that we have not found the last augment node from our module or
- * the first augment node from a "smaller" module or
- * the first node from a local module */
- if ((anchor->module == node->module) || (strcmp(anchor->module->name, node->module->name) < 0) ||
- (anchor->module == parent->module)) {
- /* insert after */
- insert_after = 1;
- break;
- }
-
- /* we have traversed all the nodes, insert before anchor (as the first node) */
- } while (anchor->prev->next);
- }
-
- /* insert */
- if (anchor) {
- if (insert_after) {
- node->next = anchor->next;
- node->prev = anchor;
- anchor->next = node;
- if (node->next) {
- /* middle node */
- node->next->prev = node;
- } else {
- /* last node */
- (*children)->prev = node;
- }
- } else {
- node->next = anchor;
- node->prev = anchor->prev;
- anchor->prev = node;
- if (anchor == *children) {
- /* first node */
- *children = node;
- } else {
- /* middle node */
- node->prev->next = node;
- }
- }
- }
-
- /* check the name uniqueness (even for an only child, it may be in case) */
- if (lys_compile_node_uniqness(ctx, parent, node->name, node)) {
- return LY_EEXIST;
- }
- } else {
- /* top-level element */
- if (!ctx->cur_mod->compiled->data) {
- ctx->cur_mod->compiled->data = node;
- } else {
- /* insert at the end of the module's top-level nodes list */
- ctx->cur_mod->compiled->data->prev->next = node;
- node->prev = ctx->cur_mod->compiled->data->prev;
- ctx->cur_mod->compiled->data->prev = node;
- }
-
- /* check the name uniqueness on top-level */
- if (lys_compile_node_uniqness(ctx, NULL, node->name, node)) {
- return LY_EEXIST;
- }
- }
-
- return LY_SUCCESS;
-}
-
-/**
* @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
@@ -3258,19 +3334,19 @@
/**
* @brief Get the grouping with the specified name from given groupings sized array.
- * @param[in] grp Sized array of groupings.
+ * @param[in] grps Linked list of groupings.
* @param[in] name Name of the grouping to find,
* @return NULL when there is no grouping with the specified name
* @return Pointer to the grouping of the specified @p name.
*/
-static struct lysp_grp *
-match_grouping(struct lysp_grp *grp, const char *name)
+static struct lysp_node_grp *
+match_grouping(struct lysp_node_grp *grps, const char *name)
{
- LY_ARRAY_COUNT_TYPE u;
+ struct lysp_node_grp *grp;
- LY_ARRAY_FOR(grp, u) {
- if (!strcmp(grp[u].name, name)) {
- return &grp[u];
+ LY_LIST_FOR(grps, grp) {
+ if (!strcmp(grp->name, name)) {
+ return grp;
}
}
@@ -3287,11 +3363,11 @@
* @return LY_ERR value.
*/
static LY_ERR
-lys_compile_uses_find_grouping(struct lysc_ctx *ctx, struct lysp_node_uses *uses_p, struct lysp_grp **grp_p,
+lys_compile_uses_find_grouping(struct lysc_ctx *ctx, struct lysp_node_uses *uses_p, struct lysp_node_grp **grp_p,
struct lysp_module **grp_pmod)
{
struct lysp_node *pnode;
- struct lysp_grp *grp;
+ struct lysp_node_grp *grp;
LY_ARRAY_COUNT_TYPE u;
const char *id, *name, *prefix, *local_pref;
size_t prefix_len, name_len;
@@ -3309,13 +3385,9 @@
/* current module, search local groupings first */
pmod = ctx->pmod->mod->parsed; /* make sure that we will start in main_module, not submodule */
for (pnode = uses_p->parent; !found && pnode; pnode = pnode->parent) {
- grp = (struct lysp_grp *)lysp_node_groupings(pnode);
- LY_ARRAY_FOR(grp, u) {
- if (!strcmp(grp[u].name, name)) {
- grp = &grp[u];
- found = ctx->pmod;
- break;
- }
+ if ((grp = match_grouping((struct lysp_node_grp *)lysp_node_groupings(pnode), name))) {
+ found = ctx->pmod;
+ break;
}
}
} else {
@@ -3375,14 +3447,11 @@
{
struct lysp_node *pnode;
struct lysc_node *child;
- struct lysp_grp *grp = NULL;
+ struct lysp_node_grp *grp = NULL;
uint32_t i, grp_stack_count;
struct lysp_module *grp_mod, *mod_old = ctx->pmod;
LY_ERR ret = LY_SUCCESS;
struct lysc_when *when_shared = NULL;
- LY_ARRAY_COUNT_TYPE u;
- struct lysc_notif **notifs = NULL;
- struct lysc_action **actions = NULL;
struct ly_set uses_child_set = {0};
/* find the referenced grouping */
@@ -3433,21 +3502,25 @@
/* compile actions */
if (grp->actions) {
+ struct lysc_node_action **actions;
actions = parent ? lysc_node_actions_p(parent) : &ctx->cur_mod->compiled->rpcs;
if (!actions) {
LOGVAL(ctx->ctx, LYVE_REFERENCE, "Invalid child %s \"%s\" of uses parent %s \"%s\" node.",
- grp->actions[0].name, lys_nodetype2str(grp->actions[0].nodetype), parent->name,
- lys_nodetype2str(parent->nodetype));
+ grp->actions->name, lys_nodetype2str(grp->actions->nodetype),
+ parent->name, lys_nodetype2str(parent->nodetype));
ret = LY_EVALID;
goto cleanup;
}
- COMPILE_OP_ARRAY_GOTO(ctx, grp->actions, *actions, parent, lys_compile_action, 0, ret, cleanup);
+ LY_LIST_FOR((struct lysp_node *)grp->actions, pnode) {
+ /* LYS_STATUS_USES in uses_status is a special bits combination to be able to detect status flags from uses */
+ ret = lys_compile_node(ctx, pnode, parent, (uses_p->flags & LYS_STATUS_MASK) | LYS_STATUS_USES, &uses_child_set);
+ LY_CHECK_GOTO(ret, cleanup);
+ }
if (uses_p->when) {
/* inherit when */
- LY_ARRAY_FOR(*actions, u) {
- ret = lys_compile_when(ctx, uses_p->when, uses_p->flags, lysc_data_node(parent),
- (struct lysc_node *)&(*actions)[u], &when_shared);
+ LY_LIST_FOR((struct lysc_node *)*actions, child) {
+ ret = lys_compile_when(ctx, uses_p->when, uses_p->flags, lysc_data_node(parent), child, &when_shared);
LY_CHECK_GOTO(ret, cleanup);
}
}
@@ -3455,21 +3528,26 @@
/* compile notifications */
if (grp->notifs) {
+ struct lysc_node_notif **notifs;
notifs = parent ? lysc_node_notifs_p(parent) : &ctx->cur_mod->compiled->notifs;
if (!notifs) {
LOGVAL(ctx->ctx, LYVE_REFERENCE, "Invalid child %s \"%s\" of uses parent %s \"%s\" node.",
- grp->notifs[0].name, lys_nodetype2str(grp->notifs[0].nodetype), parent->name,
- lys_nodetype2str(parent->nodetype));
+ grp->notifs->name, lys_nodetype2str(grp->notifs->nodetype),
+ parent->name, lys_nodetype2str(parent->nodetype));
ret = LY_EVALID;
goto cleanup;
}
- COMPILE_OP_ARRAY_GOTO(ctx, grp->notifs, *notifs, parent, lys_compile_notif, 0, ret, cleanup);
+
+ LY_LIST_FOR((struct lysp_node *)grp->notifs, pnode) {
+ /* LYS_STATUS_USES in uses_status is a special bits combination to be able to detect status flags from uses */
+ ret = lys_compile_node(ctx, pnode, parent, (uses_p->flags & LYS_STATUS_MASK) | LYS_STATUS_USES, &uses_child_set);
+ LY_CHECK_GOTO(ret, cleanup);
+ }
if (uses_p->when) {
/* inherit when */
- LY_ARRAY_FOR(*notifs, u) {
- ret = lys_compile_when(ctx, uses_p->when, uses_p->flags, lysc_data_node(parent),
- (struct lysc_node *)&(*notifs)[u], &when_shared);
+ LY_LIST_FOR((struct lysc_node *)*notifs, child) {
+ ret = lys_compile_when(ctx, uses_p->when, uses_p->flags, lysc_data_node(parent), child, &when_shared);
LY_CHECK_GOTO(ret, cleanup);
}
}
@@ -3561,7 +3639,7 @@
}
LY_ERR
-lys_compile_grouping(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysp_grp *grp)
+lys_compile_grouping(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysp_node_grp *grp)
{
LY_ERR ret;
char *path;
@@ -3614,58 +3692,12 @@
return ret;
}
-/**
- * @brief Set config flags for a node.
- *
- * @param[in] ctx Compile context.
- * @param[in] node Compiled node config to set.
- * @param[in] parent Parent of @p node.
- * @return LY_ERR value.
- */
-static LY_ERR
-lys_compile_config(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc_node *parent)
-{
- /* case never has any explicit config */
- assert((node->nodetype != LYS_CASE) || !(node->flags & LYS_CONFIG_MASK));
-
- if (ctx->options & (LYS_COMPILE_RPC_INPUT | LYS_COMPILE_RPC_OUTPUT)) {
- /* ignore config statements inside RPC/action data */
- node->flags &= ~LYS_CONFIG_MASK;
- node->flags |= (ctx->options & LYS_COMPILE_RPC_INPUT) ? LYS_CONFIG_W : LYS_CONFIG_R;
- } else if (ctx->options & LYS_COMPILE_NOTIFICATION) {
- /* ignore config statements inside Notification data */
- node->flags &= ~LYS_CONFIG_MASK;
- node->flags |= LYS_CONFIG_R;
- } else if (!(node->flags & LYS_CONFIG_MASK)) {
- /* config not explicitly set, inherit it from parent */
- if (parent) {
- node->flags |= parent->flags & LYS_CONFIG_MASK;
- } else {
- /* default is config true */
- node->flags |= LYS_CONFIG_W;
- }
- } else {
- /* config set explicitly */
- node->flags |= LYS_SET_CONFIG;
- }
-
- if (parent && (parent->flags & LYS_CONFIG_R) && (node->flags & LYS_CONFIG_W)) {
- LOGVAL(ctx->ctx, LYVE_SEMANTICS,
- "Configuration node cannot be child of any state data node.");
- return LY_EVALID;
- }
-
- return LY_SUCCESS;
-}
-
LY_ERR
lys_compile_node(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *parent, uint16_t uses_status,
struct ly_set *child_set)
{
LY_ERR ret = LY_SUCCESS;
struct lysc_node *node = NULL;
- struct lysp_node *dev_pnode = NULL;
- 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 *);
@@ -3707,6 +3739,28 @@
node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_anydata));
node_compile_spec = lys_compile_node_any;
break;
+ case LYS_RPC:
+ case LYS_ACTION:
+ if (ctx->options & (LYS_COMPILE_RPC_MASK | LYS_COMPILE_NOTIFICATION)) {
+ LOGVAL(ctx->ctx, LYVE_SEMANTICS,
+ "Action \"%s\" is placed inside %s.", pnode->name,
+ ctx->options & LYS_COMPILE_RPC_MASK ? "another RPC/action" : "notification");
+ return LY_EVALID;
+ }
+ node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_action));
+ node_compile_spec = lys_compile_node_action;
+ break;
+ case LYS_NOTIF:
+ if (ctx->options & (LYS_COMPILE_RPC_MASK | LYS_COMPILE_NOTIFICATION)) {
+ LOGVAL(ctx->ctx, LYVE_SEMANTICS,
+ "Notification \"%s\" is placed inside %s.", pnode->name,
+ ctx->options & LYS_COMPILE_RPC_MASK ? "RPC/action" : "another notification");
+ return LY_EVALID;
+ }
+ node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_notif));
+ node_compile_spec = lys_compile_node_notif;
+ ctx->options |= LYS_COMPILE_NOTIFICATION;
+ break;
case LYS_USES:
ret = lys_compile_uses(ctx, (struct lysp_node_uses *)pnode, parent, child_set);
lysc_update_path(ctx, NULL, NULL);
@@ -3718,91 +3772,9 @@
}
LY_CHECK_ERR_RET(!node, LOGMEM(ctx->ctx), LY_EMEM);
- /* compile any deviations for this node */
- LY_CHECK_ERR_GOTO(ret = lys_compile_node_deviations_refines(ctx, pnode, parent, &dev_pnode, ¬_supported),
- free(node), cleanup);
- if (not_supported) {
- free(node);
- goto cleanup;
- } else if (dev_pnode) {
- pnode = dev_pnode;
- }
+ ret = lys_compile_node_(ctx, pnode, parent, uses_status, node_compile_spec, node, child_set);
- node->nodetype = pnode->nodetype;
- node->module = ctx->cur_mod;
- 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 | LYS_COMPILE_GROUPING))) {
- 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);
-
- /* list ordering */
- if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
- if ((node->flags & LYS_CONFIG_R) && (node->flags & LYS_ORDBY_MASK)) {
- LOGWRN(ctx->ctx, "The ordered-by statement is ignored in lists representing %s (%s).",
- (ctx->options & LYS_COMPILE_RPC_OUTPUT) ? "RPC/action output parameters" :
- (ctx->options & LYS_COMPILE_NOTIFICATION) ? "notification content" : "state data", ctx->path);
- node->flags &= ~LYS_ORDBY_MASK;
- node->flags |= LYS_ORDBY_SYSTEM;
- } else if (!(node->flags & LYS_ORDBY_MASK)) {
- /* default ordering is system */
- node->flags |= LYS_ORDBY_SYSTEM;
- }
- }
-
- /* 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_GOTO(ret = lys_compile_status(ctx, &node->flags, uses_status ? uses_status : (parent ? parent->flags : 0)), error);
-
- 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);
-
- /* 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);
-
- if (pnode->when) {
- /* compile when */
- ret = lys_compile_when(ctx, pnode->when, pnode->flags, lysc_data_node(node), node, NULL);
- LY_CHECK_GOTO(ret, cleanup);
- }
-
- /* connect any augments */
- LY_CHECK_GOTO(ret = lys_compile_node_augments(ctx, node), cleanup);
-
- /* nodetype-specific part */
- LY_CHECK_GOTO(ret = node_compile_spec(ctx, pnode, node), cleanup);
-
- /* final compilation tasks that require the node to be connected */
- COMPILE_EXTS_GOTO(ctx, pnode->exts, node->exts, node, LYEXT_PAR_NODE, ret, cleanup);
- if (node->flags & LYS_MAND_TRUE) {
- /* inherit LYS_MAND_TRUE in parent containers */
- lys_compile_mandatory_parents(parent, 1);
- }
-
- if (child_set) {
- /* add the new node into set */
- LY_CHECK_GOTO(ret = ly_set_add(child_set, node, 1, NULL), cleanup);
- }
-
- goto cleanup;
-
-error:
- lysc_node_free(ctx->ctx, node, 0);
-cleanup:
ctx->options = prev_opts;
- if (ret && dev_pnode) {
- LOGVAL(ctx->ctx, LYVE_OTHER, "Compilation of a deviated and/or refined node failed.");
- }
- lysp_dev_node_free(ctx->ctx, dev_pnode);
lysc_update_path(ctx, NULL, NULL);
return ret;
}