schema compile CHANGE support for RPC/action in deviations and additional tests
diff --git a/src/parser_yang.c b/src/parser_yang.c
index 7916074..98c27d2 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -2985,7 +2985,7 @@
LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
break;
default:
- LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "action");
+ LOGVAL_YANG(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), parent ? "action" : "rpc");
return LY_EVALID;
}
}
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index bbf0d9b..37439dc 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -4888,6 +4888,7 @@
struct ly_set targets = {0};
struct lysc_node *target; /* target target of the deviation */
struct lysc_node_list *list;
+ struct lysc_action *actions;
struct lysp_deviation *dev;
struct lysp_deviate *d, **dp_new;
struct lysp_deviate_add *d_add;
@@ -4930,7 +4931,19 @@
/* resolve the target */
LY_CHECK_GOTO(lys_resolve_schema_nodeid(ctx, dev->nodeid, 0, NULL, ctx->mod, 0, 1,
(const struct lysc_node**)&target, &flags), cleanup);
-
+ if (target->nodetype == LYS_ACTION) {
+ /* move the target pointer to input/output to make them different from the action and
+ * between them. Before the devs[] item is being processed, the target pointer must be fixed
+ * back to the RPC/action node due to a better compatibility and decision code in this function.
+ * The LYSC_OPT_INTERNAL is used as a flag to this change. */
+ if (flags & LYSC_OPT_RPC_INPUT) {
+ target = (struct lysc_node*)&((struct lysc_action*)target)->input;
+ flags |= LYSC_OPT_INTERNAL;
+ } else if (flags & LYSC_OPT_RPC_OUTPUT) {
+ target = (struct lysc_node*)&((struct lysc_action*)target)->output;
+ flags |= LYSC_OPT_INTERNAL;
+ }
+ }
/* insert into the set of targets with duplicity detection */
i = ly_set_add(&targets, target, 0);
if (!devs[i]) {
@@ -5030,15 +5043,55 @@
/* apply deviations */
for (u = 0; u < devs_p.count && devs[u]; ++u) {
+ if (devs[u]->flags & LYSC_OPT_INTERNAL) {
+ /* fix the target pointer in case of RPC's/action's input/output */
+ if (devs[u]->flags & LYSC_OPT_RPC_INPUT) {
+ devs[u]->target = (struct lysc_node*)((char*)devs[u]->target - offsetof(struct lysc_action, input));
+ } else if (devs[u]->flags & LYSC_OPT_RPC_OUTPUT) {
+ devs[u]->target = (struct lysc_node*)((char*)devs[u]->target - offsetof(struct lysc_action, output));
+ }
+ }
+
/* not-supported */
if (devs[u]->not_supported) {
if (LY_ARRAY_SIZE(devs[u]->deviates) > 1) {
LOGWRN(ctx->ctx, "Useless multiple (%u) deviates on node \"%s\" since the node is not-supported.",
LY_ARRAY_SIZE(devs[u]->deviates), devs[u]->nodeid);
}
- /* remove the target node */
- lysc_disconnect(devs[u]->target);
- lysc_node_free(ctx->ctx, devs[u]->target);
+ if (devs[u]->target->nodetype == LYS_ACTION) {
+ if (devs[u]->flags & LYSC_OPT_RPC_INPUT) {
+ /* remove RPC's/action's input */
+ lysc_action_inout_free(ctx->ctx, &((struct lysc_action*)devs[u]->target)->input);
+ memset(&((struct lysc_action*)devs[u]->target)->input, 0, sizeof ((struct lysc_action*)devs[u]->target)->input);
+ } else if (devs[u]->flags & LYSC_OPT_RPC_OUTPUT) {
+ /* remove RPC's/action's output */
+ lysc_action_inout_free(ctx->ctx, &((struct lysc_action*)devs[u]->target)->output);
+ memset(&((struct lysc_action*)devs[u]->target)->output, 0, sizeof ((struct lysc_action*)devs[u]->target)->output);
+ } else {
+ /* remove RPC/action */
+ if (devs[u]->target->parent) {
+ actions = (struct lysc_action*)lysc_node_actions(devs[u]->target->parent);
+ } else {
+ actions = devs[u]->target->module->compiled->rpcs;
+ }
+ LY_ARRAY_FOR(actions, x) {
+ if (&actions[x] == (struct lysc_action*)devs[u]->target) {
+ break;
+ }
+ }
+ if (x < LY_ARRAY_SIZE(actions)) {
+ lysc_action_free(ctx->ctx, &actions[x]);
+ memmove(&actions[x], &actions[x + 1], (LY_ARRAY_SIZE(actions) - (x + 1)) * sizeof *actions);
+ LY_ARRAY_DECREMENT(actions);
+ }
+ }
+ } else if (devs[u]->target->nodetype == LYS_NOTIF) {
+ /* TODO Notification */
+ } else {
+ /* remove the target node */
+ lysc_disconnect(devs[u]->target);
+ lysc_node_free(ctx->ctx, devs[u]->target);
+ }
continue;
}
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index a17694a..062524d 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -170,7 +170,7 @@
}
-static void
+void
lysp_action_inout_free(struct ly_ctx *ctx, struct lysp_action_inout *inout)
{
struct lysp_node *node, *next;
@@ -630,29 +630,27 @@
}
void
-lysc_action_free(struct ly_ctx *ctx, struct lysc_action *action)
+lysc_action_inout_free(struct ly_ctx *ctx, struct lysc_action_inout *inout)
{
struct lysc_node *child, *child_next;
+ FREE_ARRAY(ctx, inout->exts, lysc_ext_instance_free);
+ FREE_ARRAY(ctx, inout->musts, lysc_must_free);
+ LY_LIST_FOR_SAFE(inout->data, child_next, child) {
+ lysc_node_free(ctx, child);
+ }
+}
+
+void
+lysc_action_free(struct ly_ctx *ctx, struct lysc_action *action)
+{
FREE_STRING(ctx, action->name);
FREE_STRING(ctx, action->dsc);
FREE_STRING(ctx, action->ref);
FREE_ARRAY(ctx, action->iffeatures, lysc_iffeature_free);
FREE_ARRAY(ctx, action->exts, lysc_ext_instance_free);
-
- /* input */
- FREE_ARRAY(ctx, action->input.exts, lysc_ext_instance_free);
- FREE_ARRAY(ctx, action->input.musts, lysc_must_free);
- LY_LIST_FOR_SAFE(action->input.data, child_next, child) {
- lysc_node_free(ctx, child);
- }
-
- /* output */
- FREE_ARRAY(ctx, action->output.exts, lysc_ext_instance_free);
- FREE_ARRAY(ctx, action->output.musts, lysc_must_free);
- LY_LIST_FOR_SAFE(action->output.data, child_next, child) {
- lysc_node_free(ctx, child);
- }
+ lysc_action_inout_free(ctx, &action->input);
+ lysc_action_inout_free(ctx, &action->output);
}
static void
diff --git a/src/tree_schema_helpers.c b/src/tree_schema_helpers.c
index f5b9174..57c381b 100644
--- a/src/tree_schema_helpers.c
+++ b/src/tree_schema_helpers.c
@@ -958,6 +958,10 @@
return "anydata";
case LYS_CASE:
return "case";
+ case LYS_ACTION:
+ return "RPC/action";
+ case LYS_NOTIF:
+ return "Notification";
default:
return "unknown";
}
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index 792ce51..c20daad 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -500,6 +500,22 @@
void lysc_must_free(struct ly_ctx *ctx, struct lysc_must *must);
/**
+ * @brief Free the data inside compiled input/output structure.
+ * @param[in] ctx libyang context where the string data resides in a dictionary.
+ * @param[in,out] inout Compiled inout structure to be cleaned.
+ * Since the structure is part of the RPC/action structure, it is not freed itself.
+ */
+void lysc_action_inout_free(struct ly_ctx *ctx, struct lysc_action_inout *inout);
+
+/**
+ * @brief Free the data inside compiled RPC/action structure.
+ * @param[in] ctx libyang context where the string data resides in a dictionary.
+ * @param[in,out] action Compiled action structure to be cleaned.
+ * Since the structure is typically part of the sized array, the structure itself is not freed.
+ */
+void lysc_action_free(struct ly_ctx *ctx, struct lysc_action *action);
+
+/**
* @brief Free the compiled extension instance structure.
* @param[in] ctx libyang context where the string data resides in a dictionary.
* @param[in,out] ext Compiled extension instance structure to be cleaned.