Merge branch 'master' into devel
diff --git a/src/common.c b/src/common.c
index 49e8b2b..395c41a 100644
--- a/src/common.c
+++ b/src/common.c
@@ -254,6 +254,8 @@
return "rpc";
case LYS_USES:
return "uses";
+ case LYS_ACTION:
+ return "action";
}
return NULL;
diff --git a/src/common.h b/src/common.h
index 51cb24e..1a53b19 100644
--- a/src/common.h
+++ b/src/common.h
@@ -91,7 +91,7 @@
/*
* logger
*/
-extern volatile uint8_t ly_log_level;
+extern volatile int8_t ly_log_level;
void ly_log(LY_LOG_LEVEL level, const char *format, ...);
@@ -137,6 +137,7 @@
LYE_EOF,
LYE_INSTMT,
LYE_INCHILDSTMT,
+ LYE_INPAR,
LYE_INID,
LYE_INDATE,
LYE_INARG,
@@ -166,6 +167,7 @@
LYE_CIRC_LEAFREFS,
LYE_CIRC_IMPORTS,
LYE_CIRC_INCLUDES,
+ LYE_INVER,
LYE_OBSDATA,
LYE_OBSTYPE,
@@ -190,6 +192,7 @@
LYE_NOREQINS,
LYE_NOLEAFREF,
LYE_NOMANDCHOICE,
+ LYE_INACT,
LYE_XPATH_INTOK,
LYE_XPATH_EOF,
diff --git a/src/libyang.h b/src/libyang.h
index e0c7ace..e96fc06 100644
--- a/src/libyang.h
+++ b/src/libyang.h
@@ -1082,11 +1082,11 @@
* @brief Verbosity levels of the libyang logger.
*/
typedef enum {
- LY_LLSILENT, /**< Print no messages. */
- LY_LLERR, /**< Print only error messages, default value. */
- LY_LLWRN, /**< Print error and warning messages. */
- LY_LLVRB, /**< Besides errors and warnings, print some other verbose messages. */
- LY_LLDBG /**< Print all messages including some development debug messages. */
+ LY_LLSILENT = -1, /**< Print no messages. */
+ LY_LLERR = 0, /**< Print only error messages, default value. */
+ LY_LLWRN, /**< Print error and warning messages. */
+ LY_LLVRB, /**< Besides errors and warnings, print some other verbose messages. */
+ LY_LLDBG /**< Print all messages including some development debug messages. */
} LY_LOG_LEVEL;
/**
@@ -1147,6 +1147,7 @@
LYVE_EOF, /**< unexpected end of input data */
LYVE_INSTMT, /**< invalid statement (schema) */
/* */
+ LYVE_INPAR, /**< invalid (in)direct parent (schema) */
LYVE_INID, /**< invalid identifier (schema) */
LYVE_INDATE, /**< invalid date format */
LYVE_INARG, /**< invalid value of a statement argument (schema) */
@@ -1176,6 +1177,7 @@
LYVE_CIRC_LEAFREFS,/**< circular chain of leafrefs detected (schema) */
LYVE_CIRC_IMPORTS, /**< circular chain of imports detected (schema) */
LYVE_CIRC_INCLUDES,/**< circular chain of includes detected (schema) */
+ LYVE_INVER, /**< non-matching YANG versions of module and its submodules (schema) */
LYVE_OBSDATA, /**< obsolete data instantiation (data) */
/* */
@@ -1200,6 +1202,7 @@
LYVE_NOREQINS, /**< required instance does not exits (data) */
LYVE_NOLEAFREF, /**< leaf pointed to by leafref does not exist (data) */
LYVE_NOMANDCHOICE, /**< no mandatory choice case branch exists (data) */
+ LYVE_INACT, /**< action contains some other node than container or list with keys (data) */
LYVE_XPATH_INTOK, /**< unexpected XPath token */
LYVE_XPATH_EOF, /**< unexpected end of an XPath expression */
diff --git a/src/log.c b/src/log.c
index 272ca39..a13d099 100644
--- a/src/log.c
+++ b/src/log.c
@@ -24,7 +24,7 @@
#include "tree_internal.h"
extern LY_ERR ly_errno_int;
-volatile uint8_t ly_log_level = LY_LLERR;
+volatile int8_t ly_log_level = LY_LLERR;
static void (*ly_log_clb)(LY_LOG_LEVEL level, const char *msg, const char *path);
static volatile int path_flag = 1;
@@ -134,6 +134,7 @@
/* LYE_EOF */ "Unexpected end of input data.",
/* LYE_INSTMT */ "Invalid keyword \"%s\".",
/* LYE_INCHILDSTMT */ "Invalid keyword \"%s\" as a child to \"%s\".",
+/* LYE_INPAR */ "Invalid ancestor \"%s\" of \"%s\".",
/* LYE_INID */ "Invalid identifier \"%s\" (%s).",
/* LYE_INDATE */ "Invalid date format of \"%s\", \"YYYY-MM-DD\" expected.",
/* LYE_INARG */ "Invalid value \"%s\" of \"%s\".",
@@ -163,6 +164,7 @@
/* LYE_CIRC_LEAFREFS */"A circular chain of leafrefs detected.",
/* LYE_CIRC_IMPORTS */ "A circular dependency (import) for module \"%s\".",
/* LYE_CIRC_INCLUDES */"A circular dependency (include) for submodule \"%s\".",
+/* LYE_INVER */ "Different YANG versions of a submodule and its main module.",
/* LYE_OBSDATA */ "Obsolete data \"%s\" instantiated.",
/* LYE_OBSTYPE */ "Data node \"%s\" with obsolete type \"%s\" instantiated.",
@@ -187,6 +189,7 @@
/* LYE_NOREQINS */ "Required instance of \"%s\" does not exists.",
/* LYE_NOLEAFREF */ "Leafref \"%s\" of value \"%s\" points to a non-existing leaf.",
/* LYE_NOMANDCHOICE */ "Mandatory choice \"%s\" missing a case branch.",
+/* LYE_INACT */ "Action contains a redundant %s \"%s\".",
/* LYE_XPATH_INTOK */ "Unexpected XPath token %s (%.15s).",
/* LYE_XPATH_EOF */ "Unexpected XPath expression end.",
@@ -216,6 +219,7 @@
LYVE_EOF, /* LYE_EOF */
LYVE_INSTMT, /* LYE_INSTMT */
LYVE_INSTMT, /* LYE_INCHILDSTMT */
+ LYVE_INPAR, /* LYE_INPAR */
LYVE_INID, /* LYE_INID */
LYVE_INDATE, /* LYE_INDATE */
LYVE_INARG, /* LYE_INARG */
@@ -245,6 +249,7 @@
LYVE_CIRC_LEAFREFS,/* LYE_CIRC_LEAFREFS */
LYVE_CIRC_IMPORTS, /* LYE_CIRC_IMPORTS */
LYVE_CIRC_INCLUDES,/* LYE_CIRC_INCLUDES */
+ LYVE_INVER, /* LYE_INVER */
LYVE_OBSDATA, /* LYE_OBSDATA */
LYVE_OBSDATA, /* LYE_OBSTYPE */
@@ -269,6 +274,7 @@
LYVE_NOREQINS, /* LYE_NOREQINS */
LYVE_NOLEAFREF, /* LYE_NOLEAFREF */
LYVE_NOMANDCHOICE, /* LYE_NOMANDCHOICE */
+ LYVE_INACT, /* LYE_INACT */
LYVE_XPATH_INTOK, /* LYE_XPATH_INTOK */
LYVE_XPATH_EOF, /* LYE_XPATH_EOF */
diff --git a/src/parser.c b/src/parser.c
index 1daef7b..d1e333e 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -125,15 +125,18 @@
};
int
-lyp_is_rpc(struct lys_node *node)
+lyp_is_rpc_action(struct lys_node *node)
{
assert(node);
while (lys_parent(node)) {
node = lys_parent(node);
+ if (node->nodetype == LYS_ACTION) {
+ break;
+ }
}
- if (node->nodetype == LYS_RPC) {
+ if (node->nodetype & (LYS_RPC | LYS_ACTION)) {
return 1;
} else {
return 0;
diff --git a/src/parser.h b/src/parser.h
index a499a33..a35bcfb 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -79,12 +79,12 @@
int dup_identities_check(const char *id, struct lys_module *module);
/**
- * @brief Get know if the node is part of the RPC's input/output
+ * @brief Get know if the node is part of the RPC/action's input/output
*
* @param node Schema node to be examined.
* @return 1 for true, 0 for false
*/
-int lyp_is_rpc(struct lys_node *node);
+int lyp_is_rpc_action(struct lys_node *node);
/**
* @brief Check validity of parser options.
diff --git a/src/parser_xml.c b/src/parser_xml.c
index e3fb116..9cc48a8 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -116,8 +116,8 @@
/* logs directly */
static int
-xml_parse_data(struct ly_ctx *ctx, struct lyxml_elem *xml, const struct lys_node *schema_parent, struct lyd_node *parent,
- struct lyd_node *prev, int options, struct unres_data *unres, struct lyd_node **result)
+xml_parse_data(struct ly_ctx *ctx, struct lyxml_elem *xml, struct lyd_node *parent, struct lyd_node *prev, int options,
+ struct unres_data *unres, struct lyd_node **result, struct lyd_node **action)
{
struct lyd_node *diter, *dlast, *first_sibling;
struct lys_node *schema = NULL;
@@ -142,9 +142,7 @@
}
/* find schema node */
- if (schema_parent) {
- schema = xml_data_search_schemanode(xml, schema_parent->child, options);
- } else if (!parent) {
+ if (!parent) {
/* starting in root */
for (i = 0; i < ctx->models.used; i++) {
/* match data model based on namespace */
@@ -156,6 +154,10 @@
if (schema->nodetype != LYS_RPC) {
continue;
}
+ } else if (options & LYD_OPT_ACTION) {
+ if (!(schema->nodetype & (LYS_CONTAINER | LYS_LIST))) {
+ continue;
+ }
} else if (options & LYD_OPT_NOTIF) {
if (schema->nodetype != LYS_NOTIF) {
continue;
@@ -192,6 +194,7 @@
case LYS_LIST:
case LYS_NOTIF:
case LYS_RPC:
+ case LYS_ACTION:
*result = calloc(1, sizeof **result);
havechildren = 1;
break;
@@ -357,6 +360,9 @@
((struct lyd_node_anyxml *)*result)->xml_struct = 0;
((struct lyd_node_anyxml *)*result)->value.str = lydict_insert(ctx, xml->content, 0);
}
+ } else if (schema->nodetype == LYS_ACTION) {
+ options &= ~LYS_ACTION;
+ options |= LYS_RPC;
}
/* first part of validation checks */
@@ -433,14 +439,22 @@
}
}
+ if ((*result)->schema->nodetype == LYS_ACTION) {
+ if (!(options & LYD_OPT_ACTION) || *action) {
+ LOGVAL(LYE_SPEC, LY_VLOG_LYD, (*result), "Unexpected action node \"%s\".", (*result)->schema->name);
+ goto error;
+ }
+ *action = *result;
+ }
+
/* process children */
if (havechildren && xml->child) {
diter = dlast = NULL;
LY_TREE_FOR_SAFE(xml->child, next, child) {
if (schema->nodetype & (LYS_RPC | LYS_NOTIF)) {
- r = xml_parse_data(ctx, child, NULL, *result, dlast, 0, unres, &diter);
+ r = xml_parse_data(ctx, child, *result, dlast, 0, unres, &diter, action);
} else {
- r = xml_parse_data(ctx, child, NULL, *result, dlast, options, unres, &diter);
+ r = xml_parse_data(ctx, child, *result, dlast, options, unres, &diter, action);
}
if (r) {
goto error;
@@ -499,8 +513,8 @@
va_list ap;
int r;
struct unres_data *unres = NULL;
- struct lys_node *rpc = NULL;
- struct lyd_node *result = NULL, *iter, *last;
+ struct lys_node *rpc_act = NULL;
+ struct lyd_node *result = NULL, *iter, *last, *reply_parent = NULL, *action = NULL;
struct lyxml_elem *xmlstart, *xmlelem, *xmlaux;
ly_errno = LY_SUCCESS;
@@ -529,11 +543,13 @@
va_start(ap, options);
if (options & LYD_OPT_RPCREPLY) {
- rpc = va_arg(ap, struct lys_node*);
- if (!rpc || (rpc->nodetype != LYS_RPC)) {
+ rpc_act = va_arg(ap, struct lys_node *);
+ if (!rpc_act || !(rpc_act->nodetype & (LYS_RPC | LYS_ACTION))) {
LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
goto error;
}
+ reply_parent = _lyd_new(NULL, rpc_act);
+ result = reply_parent;
}
if (!(options & LYD_OPT_NOSIBLINGS)) {
@@ -549,10 +565,18 @@
} else {
xmlstart = *root;
}
- iter = result = last = NULL;
+ if ((options & LYD_OPT_RPC)
+ && !strcmp(xmlstart->name, "action") && !strcmp(xmlstart->ns->value, "urn:ietf:params:xml:ns:yang:1")) {
+ /* it's an action, not a simple RPC */
+ xmlstart = xmlstart->child;
+ options &= ~LYD_OPT_RPC;
+ options |= LYD_OPT_ACTION;
+ }
+
+ iter = last = NULL;
LY_TREE_FOR_SAFE(xmlstart, xmlaux, xmlelem) {
- r = xml_parse_data(ctx, xmlelem, rpc, NULL, last, options, unres, &iter);
+ r = xml_parse_data(ctx, xmlelem, reply_parent, last, options, unres, &iter, &action);
if (r) {
goto error;
} else if (options & LYD_OPT_DESTRUCT) {
@@ -572,28 +596,17 @@
}
}
- if (options & LYD_OPT_RPCREPLY) {
- last = result;
- result = lyd_new_output(NULL, lys_node_module(rpc), rpc->name);
- /* insert all the output parameters into RPC */
- do {
- iter = last;
- last = iter->next;
- if (lyd_insert(result, iter)) {
- LOGINT;
- lyd_free_withsiblings(last);
- goto error;
- }
- } while (last);
- }
-
/* check for missing top level mandatory nodes */
if (lyd_check_topmandatory(result, ctx, options)) {
goto error;
}
/* add/validate default values, unres */
- if (lyd_defaults_add_unres(&result, options, ctx, unres)) {
+ if (action) {
+ if (lyd_defaults_add_unres(&action, options, ctx, unres)) {
+ goto error;
+ }
+ } else if (lyd_defaults_add_unres(&result, options, ctx, unres)) {
goto error;
}
diff --git a/src/parser_yang.c b/src/parser_yang.c
index 096cbf4..5411a66 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -38,7 +38,6 @@
int size;
struct lys_tpdf *tpdf;
-
if (root) {
node = root;
}
@@ -60,13 +59,13 @@
size = ((struct lys_node_grp *)child)->tpdf_size;
break;
case LYS_RPC:
- tpdf = ((struct lys_node_rpc *)child)->tpdf;
- size = ((struct lys_node_rpc *)child)->tpdf_size;
+ tpdf = ((struct lys_node_rpc_action *)child)->tpdf;
+ size = ((struct lys_node_rpc_action *)child)->tpdf_size;
break;
case LYS_INPUT:
case LYS_OUTPUT:
- tpdf = ((struct lys_node_rpc_inout *)child)->tpdf;
- size = ((struct lys_node_rpc_inout *)child)->tpdf_size;
+ tpdf = ((struct lys_node_inout *)child)->tpdf;
+ size = ((struct lys_node_inout *)child)->tpdf_size;
break;
case LYS_NOTIF:
tpdf = ((struct lys_node_notif *)child)->tpdf;
@@ -266,22 +265,18 @@
}
free(value);
- /* hack - store pointer to the parent node for later status check */
if (type == FEATURE_KEYWORD) {
f = (struct lys_feature *) ptr;
- f->features[f->features_size] = f;
- ret = unres_schema_add_str(module, unres, &f->features[f->features_size], UNRES_IFFEAT, exp);
- f->features_size++;
+ ret = resolve_iffeature_compile(&f->iffeature[f->iffeature_size], exp, (struct lys_node *)f, unres);
+ f->iffeature_size++;
} else {
n = (struct lys_node *) ptr;
- n->features[n->features_size] = (struct lys_feature *) n;
- ret = unres_schema_add_str(module, unres, &n->features[n->features_size], UNRES_IFFEAT, exp);
- n->features_size++;
+ ret = resolve_iffeature_compile(&n->iffeature[n->iffeature_size], exp, n, unres);
+ n->iffeature_size++;
}
-
lydict_remove(module->ctx, exp);
- if (ret == -1) {
+ if (ret) {
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
@@ -1307,13 +1302,14 @@
((struct lys_node_list *)parent)->tpdf_size++;
break;
case LYS_RPC:
- ret = &((struct lys_node_rpc *)parent)->tpdf[((struct lys_node_rpc *)parent)->tpdf_size];
- ((struct lys_node_rpc *)parent)->tpdf_size++;
+ case LYS_ACTION:
+ ret = &((struct lys_node_rpc_action *)parent)->tpdf[((struct lys_node_rpc_action *)parent)->tpdf_size];
+ ((struct lys_node_rpc_action *)parent)->tpdf_size++;
break;
case LYS_INPUT:
case LYS_OUTPUT:
- ret = &((struct lys_node_rpc_inout *)parent)->tpdf[((struct lys_node_rpc_inout *)parent)->tpdf_size];
- ((struct lys_node_rpc_inout *)parent)->tpdf_size++;
+ ret = &((struct lys_node_inout *)parent)->tpdf[((struct lys_node_inout *)parent)->tpdf_size];
+ ((struct lys_node_inout *)parent)->tpdf_size++;
break;
case LYS_NOTIF:
ret = &((struct lys_node_notif *)parent)->tpdf[((struct lys_node_notif *)parent)->tpdf_size];
diff --git a/src/parser_yang.h b/src/parser_yang.h
index e2a4c3d..9e5a518 100644
--- a/src/parser_yang.h
+++ b/src/parser_yang.h
@@ -82,8 +82,8 @@
struct lys_node_leaf *ptr_leaf;
struct lys_tpdf *ptr_tpdf;
struct lys_node_augment *ptr_augment;
- struct lys_node_rpc *ptr_rpc;
- struct lys_node_rpc_inout *ptr_inout;
+ struct lys_node_rpc_action *ptr_rpc;
+ struct lys_node_inout *ptr_inout;
};
uint8_t flag;
};
diff --git a/src/parser_yang_bis.c b/src/parser_yang_bis.c
index 5f6254d..5d2d83e 100644
--- a/src/parser_yang_bis.c
+++ b/src/parser_yang_bis.c
@@ -3086,7 +3086,7 @@
case 24:
- { if (strlen(yyget_text(scanner))!=1 || yyget_text(scanner)[0]!='1') {
+ { if (strcmp(yyget_text(scanner), "1") && strcmp(yyget_text(scanner), "1.1")) {
YYABORT;
}
}
@@ -3096,7 +3096,7 @@
case 26:
{ if (read_all) {
- if (strlen(s)!=1 || s[0]!='1') {
+ if (strcmp(s, "1") && strcmp(s, "1.1")) {
free(s);
YYABORT;
}
@@ -3614,9 +3614,9 @@
{ if (read_all) {
if (size_arrays->node[size_arrays->next].if_features) {
- ((struct lys_feature*)actual)->features = calloc(size_arrays->node[size_arrays->next].if_features,
- sizeof *((struct lys_feature*)actual)->features);
- if (!((struct lys_feature*)actual)->features) {
+ ((struct lys_feature*)actual)->iffeature = calloc(size_arrays->node[size_arrays->next].if_features,
+ sizeof *((struct lys_feature*)actual)->iffeature);
+ if (!((struct lys_feature*)actual)->iffeature) {
LOGMEM;
YYABORT;
}
@@ -4558,8 +4558,8 @@
(yyval.nodes).container = actual;
actual_type = CONTAINER_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- (yyval.nodes).container->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).container->features);
- if (!(yyval.nodes).container->features) {
+ (yyval.nodes).container->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).container->iffeature);
+ if (!(yyval.nodes).container->iffeature) {
LOGMEM;
YYABORT;
}
@@ -4740,8 +4740,8 @@
(yyval.nodes).node.flag = 0;
actual_type = LEAF_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- (yyval.nodes).node.ptr_leaf->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_leaf->features);
- if (!(yyval.nodes).node.ptr_leaf->features) {
+ (yyval.nodes).node.ptr_leaf->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_leaf->iffeature);
+ if (!(yyval.nodes).node.ptr_leaf->iffeature) {
LOGMEM;
YYABORT;
}
@@ -4933,8 +4933,8 @@
(yyval.nodes).node.flag = 0;
actual_type = LEAF_LIST_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- (yyval.nodes).node.ptr_leaflist->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_leaflist->features);
- if (!(yyval.nodes).node.ptr_leaflist->features) {
+ (yyval.nodes).node.ptr_leaflist->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_leaflist->iffeature);
+ if (!(yyval.nodes).node.ptr_leaflist->iffeature) {
LOGMEM;
YYABORT;
}
@@ -5168,8 +5168,8 @@
(yyval.nodes).node.flag = 0;
actual_type = LIST_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- (yyval.nodes).node.ptr_list->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_list->features);
- if (!(yyval.nodes).node.ptr_list->features) {
+ (yyval.nodes).node.ptr_list->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_list->iffeature);
+ if (!(yyval.nodes).node.ptr_list->iffeature) {
LOGMEM;
YYABORT;
}
@@ -5441,8 +5441,8 @@
(yyval.nodes).choice.s = NULL;
actual_type = CHOICE_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- (yyval.nodes).choice.ptr_choice->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).choice.ptr_choice->features);
- if (!(yyval.nodes).choice.ptr_choice->features) {
+ (yyval.nodes).choice.ptr_choice->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).choice.ptr_choice->iffeature);
+ if (!(yyval.nodes).choice.ptr_choice->iffeature) {
LOGMEM;
YYABORT;
}
@@ -5609,8 +5609,8 @@
(yyval.nodes).cs = actual;
actual_type = CASE_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- (yyval.nodes).cs->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).cs->features);
- if (!(yyval.nodes).cs->features) {
+ (yyval.nodes).cs->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).cs->iffeature);
+ if (!(yyval.nodes).cs->iffeature) {
LOGMEM;
YYABORT;
}
@@ -5706,15 +5706,15 @@
(yyval.nodes).anyxml = actual;
actual_type = ANYXML_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- (yyval.nodes).anyxml->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).anyxml->features);
- if (!(yyval.nodes).anyxml->features) {
+ (yyval.nodes).anyxml->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).anyxml->iffeature);
+ if (!(yyval.nodes).anyxml->iffeature) {
LOGMEM;
YYABORT;
}
}
if (size_arrays->node[size_arrays->next].must) {
(yyval.nodes).anyxml->must = calloc(size_arrays->node[size_arrays->next].must, sizeof *(yyval.nodes).anyxml->must);
- if (!(yyval.nodes).anyxml->features || !(yyval.nodes).anyxml->must) {
+ if (!(yyval.nodes).anyxml->iffeature || !(yyval.nodes).anyxml->must) {
LOGMEM;
YYABORT;
}
@@ -5847,8 +5847,8 @@
(yyval.nodes).uses.config_inherit = config_inherit;
actual_type = USES_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- (yyval.nodes).uses.ptr_uses->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).uses.ptr_uses->features);
- if (!(yyval.nodes).uses.ptr_uses->features) {
+ (yyval.nodes).uses.ptr_uses->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).uses.ptr_uses->iffeature);
+ if (!(yyval.nodes).uses.ptr_uses->iffeature) {
LOGMEM;
YYABORT;
}
@@ -6247,8 +6247,8 @@
(yyval.nodes).node.flag = 0;
actual_type = AUGMENT_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- (yyval.nodes).node.ptr_augment->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_augment->features);
- if (!(yyval.nodes).node.ptr_augment->features) {
+ (yyval.nodes).node.ptr_augment->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_augment->iffeature);
+ if (!(yyval.nodes).node.ptr_augment->iffeature) {
LOGMEM;
YYABORT;
}
@@ -6357,7 +6357,7 @@
case 421:
{ if (read_all) {
- if (!(actual = yang_read_node(trg, NULL, s, LYS_RPC, sizeof(struct lys_node_rpc)))) {
+ if (!(actual = yang_read_node(trg, NULL, s, LYS_RPC, sizeof(struct lys_node_rpc_action)))) {
YYABORT;
}
data_node = actual;
@@ -6381,8 +6381,8 @@
(yyval.nodes).node.flag = 0;
actual_type = RPC_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- (yyval.nodes).node.ptr_rpc->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_rpc->features);
- if (!(yyval.nodes).node.ptr_rpc->features) {
+ (yyval.nodes).node.ptr_rpc->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).node.ptr_rpc->iffeature);
+ if (!(yyval.nodes).node.ptr_rpc->iffeature) {
LOGMEM;
YYABORT;
}
@@ -6523,7 +6523,7 @@
LOGMEM;
YYABORT;
}
- if (!(actual = yang_read_node(trg, actual, s, LYS_INPUT, sizeof(struct lys_node_rpc_inout)))) {
+ if (!(actual = yang_read_node(trg, actual, s, LYS_INPUT, sizeof(struct lys_node_inout)))) {
YYABORT;
}
data_node = actual;
@@ -6615,7 +6615,7 @@
LOGMEM;
YYABORT;
}
- if (!(actual = yang_read_node(trg, actual, s, LYS_OUTPUT, sizeof(struct lys_node_rpc_inout)))) {
+ if (!(actual = yang_read_node(trg, actual, s, LYS_OUTPUT, sizeof(struct lys_node_inout)))) {
YYABORT;
}
data_node = actual;
@@ -6669,8 +6669,8 @@
(yyval.nodes).notif = actual;
actual_type = NOTIFICATION_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- (yyval.nodes).notif->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).notif->features);
- if (!(yyval.nodes).notif->features) {
+ (yyval.nodes).notif->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *(yyval.nodes).notif->iffeature);
+ if (!(yyval.nodes).notif->iffeature) {
LOGMEM;
YYABORT;
}
diff --git a/src/parser_yin.c b/src/parser_yin.c
index 73e5600..348cb2e 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -67,6 +67,8 @@
struct unres_schema *unres);
static struct lys_node *read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
int resolve, struct unres_schema *unres);
+static struct lys_node *read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
+ int resolve, struct unres_schema *unres);
static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin);
/* logs directly */
@@ -90,26 +92,24 @@
/* logs directly */
static int
-fill_yin_iffeature(struct lys_node *parent, struct lyxml_elem *yin, struct lys_feature **iffeat, struct unres_schema *unres)
+fill_yin_iffeature(struct lys_node *parent, struct lyxml_elem *yin, struct lys_iffeature *iffeat, struct unres_schema *unres)
{
int r;
const char *value;
GETVAL(value, yin, "name");
if (!(value = transform_schema2json(parent->module, value))) {
+error:
return EXIT_FAILURE;
}
- /* HACK - store pointer to the parent node for later status check */
- *iffeat = (struct lys_feature *)parent;
- r = unres_schema_add_str(parent->module, unres, iffeat, UNRES_IFFEAT, value);
+ r = resolve_iffeature_compile(iffeat, value, parent, unres);
lydict_remove(parent->module->ctx, value);
- if (!r) {
- return EXIT_SUCCESS;
+ if (r) {
+ return EXIT_FAILURE;
}
-error:
- return EXIT_FAILURE;
+ return EXIT_SUCCESS;
}
/* logs directly */
@@ -1051,15 +1051,15 @@
}
if (c) {
- f->features = calloc(c, sizeof *f->features);
- if (!f->features) {
+ f->iffeature = calloc(c, sizeof *f->iffeature);
+ if (!f->iffeature) {
LOGMEM;
goto error;
}
}
LY_TREE_FOR(yin->child, child) {
- ret = fill_yin_iffeature((struct lys_node *)f, child, &f->features[f->features_size], unres);
- f->features_size++;
+ ret = fill_yin_iffeature((struct lys_node *)f, child, &f->iffeature[f->iffeature_size], unres);
+ f->iffeature_size++;
if (ret) {
goto error;
}
@@ -2015,6 +2015,8 @@
node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
} else if (!strcmp(child->name, "anyxml")) {
node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
+ } else if (!strcmp(child->name, "action")) {
+ node = read_yin_rpc_action(module, (struct lys_node *)aug, child, 0, unres);
} else {
LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
goto error;
@@ -2029,8 +2031,8 @@
}
if (c) {
- aug->features = calloc(c, sizeof *aug->features);
- if (!aug->features) {
+ aug->iffeature = calloc(c, sizeof *aug->iffeature);
+ if (!aug->iffeature) {
LOGMEM;
goto error;
}
@@ -2038,8 +2040,8 @@
LY_TREE_FOR_SAFE(yin->child, next, child) {
if (!strcmp(child->name, "if-feature")) {
- ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->features[aug->features_size], unres);
- aug->features_size++;
+ ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->iffeature[aug->iffeature_size], unres);
+ aug->iffeature_size++;
if (ret) {
goto error;
}
@@ -2654,15 +2656,15 @@
}
if (c_ftrs) {
- cs->features = calloc(c_ftrs, sizeof *cs->features);
- if (!cs->features) {
+ cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
+ if (!cs->iffeature) {
LOGMEM;
goto error;
}
}
LY_TREE_FOR(yin->child, sub) {
- ret = fill_yin_iffeature(retval, sub, &cs->features[cs->features_size], unres);
- cs->features_size++;
+ ret = fill_yin_iffeature(retval, sub, &cs->iffeature[cs->iffeature_size], unres);
+ cs->iffeature_size++;
if (ret) {
goto error;
}
@@ -2823,16 +2825,16 @@
}
if (c_ftrs) {
- choice->features = calloc(c_ftrs, sizeof *choice->features);
- if (!choice->features) {
+ choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
+ if (!choice->iffeature) {
LOGMEM;
goto error;
}
}
LY_TREE_FOR(yin->child, sub) {
- ret = fill_yin_iffeature(retval, sub, &choice->features[choice->features_size], unres);
- choice->features_size++;
+ ret = fill_yin_iffeature(retval, sub, &choice->iffeature[choice->iffeature_size], unres);
+ choice->iffeature_size++;
if (ret) {
goto error;
}
@@ -2958,8 +2960,8 @@
}
}
if (c_ftrs) {
- anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
- if (!anyxml->features) {
+ anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
+ if (!anyxml->iffeature) {
LOGMEM;
goto error;
}
@@ -2973,8 +2975,8 @@
goto error;
}
} else if (!strcmp(sub->name, "if-feature")) {
- r = fill_yin_iffeature(retval, sub, &anyxml->features[anyxml->features_size], unres);
- anyxml->features_size++;
+ r = fill_yin_iffeature(retval, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
+ anyxml->iffeature_size++;
if (r) {
goto error;
}
@@ -3128,8 +3130,8 @@
}
}
if (c_ftrs) {
- leaf->features = calloc(c_ftrs, sizeof *leaf->features);
- if (!leaf->features) {
+ leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
+ if (!leaf->iffeature) {
LOGMEM;
goto error;
}
@@ -3143,8 +3145,8 @@
goto error;
}
} else if (!strcmp(sub->name, "if-feature")) {
- r = fill_yin_iffeature(retval, sub, &leaf->features[leaf->features_size], unres);
- leaf->features_size++;
+ r = fill_yin_iffeature(retval, sub, &leaf->iffeature[leaf->iffeature_size], unres);
+ leaf->iffeature_size++;
if (r) {
goto error;
}
@@ -3345,8 +3347,8 @@
}
}
if (c_ftrs) {
- llist->features = calloc(c_ftrs, sizeof *llist->features);
- if (!llist->features) {
+ llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
+ if (!llist->iffeature) {
LOGMEM;
goto error;
}
@@ -3360,8 +3362,8 @@
goto error;
}
} else if (!strcmp(sub->name, "if-feature")) {
- r = fill_yin_iffeature(retval, sub, &llist->features[llist->features_size], unres);
- llist->features_size++;
+ r = fill_yin_iffeature(retval, sub, &llist->iffeature[llist->iffeature_size], unres);
+ llist->iffeature_size++;
if (r) {
goto error;
}
@@ -3433,7 +3435,8 @@
!strcmp(sub->name, "choice") ||
!strcmp(sub->name, "uses") ||
!strcmp(sub->name, "grouping") ||
- !strcmp(sub->name, "anyxml")) {
+ !strcmp(sub->name, "anyxml") ||
+ !strcmp(sub->name, "action")) {
lyxml_unlink_elem(module->ctx, sub, 2);
lyxml_add_child(module->ctx, &root, sub);
@@ -3598,8 +3601,8 @@
}
}
if (c_ftrs) {
- list->features = calloc(c_ftrs, sizeof *list->features);
- if (!list->features) {
+ list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
+ if (!list->iffeature) {
LOGMEM;
goto error;
}
@@ -3612,8 +3615,8 @@
goto error;
}
} else if (!strcmp(sub->name, "if-feature")) {
- r = fill_yin_iffeature(retval, sub, &list->features[list->features_size], unres);
- list->features_size++;
+ r = fill_yin_iffeature(retval, sub, &list->iffeature[list->iffeature_size], unres);
+ list->iffeature_size++;
if (r) {
goto error;
}
@@ -3644,6 +3647,8 @@
node = read_yin_grouping(module, retval, sub, resolve, unres);
} else if (!strcmp(sub->name, "anyxml")) {
node = read_yin_anyxml(module, retval, sub, resolve, unres);
+ } else if (!strcmp(sub->name, "action")) {
+ node = read_yin_rpc_action(module, retval, sub, resolve, unres);
} else {
LOGINT;
goto error;
@@ -3770,7 +3775,8 @@
!strcmp(sub->name, "choice") ||
!strcmp(sub->name, "uses") ||
!strcmp(sub->name, "grouping") ||
- !strcmp(sub->name, "anyxml")) {
+ !strcmp(sub->name, "anyxml") ||
+ !strcmp(sub->name, "action")) {
lyxml_unlink_elem(module->ctx, sub, 2);
lyxml_add_child(module->ctx, &root, sub);
@@ -3803,8 +3809,8 @@
}
}
if (c_ftrs) {
- cont->features = calloc(c_ftrs, sizeof *cont->features);
- if (!cont->features) {
+ cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
+ if (!cont->iffeature) {
LOGMEM;
goto error;
}
@@ -3824,8 +3830,8 @@
goto error;
}
} else if (!strcmp(sub->name, "if-feature")) {
- r = fill_yin_iffeature(retval, sub, &cont->features[cont->features_size], unres);
- cont->features_size++;
+ r = fill_yin_iffeature(retval, sub, &cont->iffeature[cont->iffeature_size], unres);
+ cont->iffeature_size++;
if (r) {
goto error;
}
@@ -3850,6 +3856,8 @@
node = read_yin_grouping(module, retval, sub, resolve, unres);
} else if (!strcmp(sub->name, "anyxml")) {
node = read_yin_anyxml(module, retval, sub, resolve, unres);
+ } else if (!strcmp(sub->name, "action")) {
+ node = read_yin_rpc_action(module, retval, sub, resolve, unres);
}
if (!node) {
goto error;
@@ -3920,7 +3928,8 @@
!strcmp(sub->name, "choice") ||
!strcmp(sub->name, "uses") ||
!strcmp(sub->name, "grouping") ||
- !strcmp(sub->name, "anyxml")) {
+ !strcmp(sub->name, "anyxml") ||
+ !strcmp(sub->name, "action")) {
lyxml_unlink_elem(module->ctx, sub, 2);
lyxml_add_child(module->ctx, &root, sub);
@@ -3970,6 +3979,8 @@
node = read_yin_grouping(module, retval, sub, resolve, unres);
} else if (!strcmp(sub->name, "anyxml")) {
node = read_yin_anyxml(module, retval, sub, resolve, unres);
+ } else if (!strcmp(sub->name, "action")) {
+ node = read_yin_rpc_action(module, retval, sub, resolve, unres);
}
if (!node) {
goto error;
@@ -3998,7 +4009,7 @@
struct lyxml_elem *sub, *next, root;
struct lys_node *node = NULL;
struct lys_node *retval = NULL;
- struct lys_node_rpc_inout *inout;
+ struct lys_node_inout *inout;
int r;
int c_tpdf = 0;
@@ -4195,8 +4206,8 @@
}
}
if (c_ftrs) {
- notif->features = calloc(c_ftrs, sizeof *notif->features);
- if (!notif->features) {
+ notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
+ if (!notif->iffeature) {
LOGMEM;
goto error;
}
@@ -4210,8 +4221,8 @@
goto error;
}
} else if (!strcmp(sub->name, "if-feature")) {
- r = fill_yin_iffeature(retval, sub, ¬if->features[notif->features_size], unres);
- notif->features_size++;
+ r = fill_yin_iffeature(retval, sub, ¬if->iffeature[notif->iffeature_size], unres);
+ notif->iffeature_size++;
if (r) {
goto error;
}
@@ -4258,16 +4269,26 @@
/* logs directly */
static struct lys_node *
-read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
- struct unres_schema *unres)
+read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
+ struct unres_schema *unres)
{
struct lyxml_elem *sub, *next, root;
struct lys_node *node = NULL;
struct lys_node *retval;
- struct lys_node_rpc *rpc;
+ struct lys_node_rpc_action *rpc;
int r;
int c_tpdf = 0, c_ftrs = 0;
+ if (!strcmp(yin->name, "action")) {
+ for (node = parent; node; node = lys_parent(node)) {
+ if (node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)
+ || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
+ LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
+ return NULL;
+ }
+ }
+ }
+
/* init */
memset(&root, 0, sizeof root);
@@ -4276,7 +4297,7 @@
LOGMEM;
return NULL;
}
- rpc->nodetype = LYS_RPC;
+ rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
rpc->prev = (struct lys_node *)rpc;
retval = (struct lys_node *)rpc;
@@ -4310,8 +4331,8 @@
lyxml_add_child(module->ctx, &root, sub);
} else if (!strcmp(sub->name, "output")) {
if (rpc->child
- && (rpc->child->nodetype == LYS_INPUT
- || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
+ && (rpc->child->nodetype == LYS_OUTPUT
+ || (rpc->child->next && rpc->child->next->nodetype == LYS_OUTPUT))) {
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
goto error;
}
@@ -4343,8 +4364,8 @@
}
}
if (c_ftrs) {
- rpc->features = calloc(c_ftrs, sizeof *rpc->features);
- if (!rpc->features) {
+ rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
+ if (!rpc->iffeature) {
LOGMEM;
goto error;
}
@@ -4358,8 +4379,8 @@
goto error;
}
} else if (!strcmp(sub->name, "if-feature")) {
- r = fill_yin_iffeature(retval, sub, &rpc->features[rpc->features_size], unres);
- rpc->features_size++;
+ r = fill_yin_iffeature(retval, sub, &rpc->iffeature[rpc->iffeature_size], unres);
+ rpc->iffeature_size++;
if (r) {
goto error;
}
@@ -4370,9 +4391,7 @@
LY_TREE_FOR_SAFE(root.child, next, sub) {
if (!strcmp(sub->name, "grouping")) {
node = read_yin_grouping(module, retval, sub, resolve, unres);
- } else if (!strcmp(sub->name, "input")) {
- node = read_yin_input_output(module, retval, sub, resolve, unres);
- } else if (!strcmp(sub->name, "output")) {
+ } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
node = read_yin_input_output(module, retval, sub, resolve, unres);
}
if (!node) {
@@ -4482,8 +4501,8 @@
}
}
if (c_ftrs) {
- uses->features = calloc(c_ftrs, sizeof *uses->features);
- if (!uses->features) {
+ uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
+ if (!uses->iffeature) {
LOGMEM;
goto error;
}
@@ -4503,8 +4522,8 @@
goto error;
}
} else if (!strcmp(sub->name, "if-feature")) {
- r = fill_yin_iffeature(retval, sub, &uses->features[uses->features_size], unres);
- uses->features_size++;
+ r = fill_yin_iffeature(retval, sub, &uses->iffeature[uses->iffeature_size], unres);
+ uses->iffeature_size++;
if (r) {
goto error;
}
@@ -4703,20 +4722,36 @@
goto error;
}
} else if (!strcmp(child->name, "yang-version")) {
- /* TODO: support YANG 1.1 ? */
if (version_flag) {
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
goto error;
}
GETVAL(value, child, "value");
- if (strcmp(value, "1")) {
+ if (strcmp(value, "1") && strcmp(value, "1.1")) {
LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
goto error;
}
version_flag = 1;
- if (!submodule) {
- module->version = 1;
- } /* TODO else check for the submodule's same version as in main module, waits for YANG 1.1 support */
+ if (!strcmp(value, "1")) {
+ if (submodule) {
+ if (module->version > 1) {
+ LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
+ goto error;
+ }
+ } else {
+ module->version = 1;
+ }
+ } else {
+ if (submodule) {
+ if (module->version != 2) {
+ LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
+ goto error;
+ }
+ } else {
+ module->version = 2;
+ }
+ }
+
lyxml_free(ctx, child);
} else if (!strcmp(child->name, "extension")) {
@@ -4993,7 +5028,7 @@
} else if (!strcmp(child->name, "anyxml")) {
node = read_yin_anyxml(trg, NULL, child, 1, unres);
} else if (!strcmp(child->name, "rpc")) {
- node = read_yin_rpc(trg, NULL, child, 0, unres);
+ node = read_yin_rpc_action(trg, NULL, child, 0, unres);
} else if (!strcmp(child->name, "notification")) {
node = read_yin_notif(trg, NULL, child, 0, unres);
}
diff --git a/src/printer.c b/src/printer.c
index 91c13e6..d223607 100644
--- a/src/printer.c
+++ b/src/printer.c
@@ -134,6 +134,75 @@
}
static int
+write_iff(struct lyout *out, const struct lys_module *module, struct lys_iffeature *expr, int *index_e, int *index_f)
+{
+ int count = 0, brackets_flag = *index_e;
+ uint8_t op;
+
+ op = iff_getop(expr->expr, *index_e);
+ (*index_e)++;
+
+ switch (op) {
+ case LYS_IFF_F:
+ if (lys_main_module(expr->features[*index_f]->module) != lys_main_module(module)) {
+ count += ly_print(out, "%s:", transform_module_name2import_prefix(module, lys_main_module(expr->features[*index_f]->module)->name));
+ }
+ count += ly_print(out, expr->features[*index_f]->name);
+ (*index_f)++;
+ break;
+ case LYS_IFF_NOT:
+ op = iff_getop(expr->expr, *index_e);
+ if (op == LYS_IFF_F) {
+ /* negation about sole feature */
+ brackets_flag = 0;
+ } else {
+ /* negation around expression */
+ brackets_flag = 1;
+ }
+
+ count += ly_print(out, "not ");
+ if (brackets_flag) {
+ count += ly_print(out, "(");
+ }
+ count += write_iff(out, module, expr, index_e, index_f);
+ if (brackets_flag) {
+ count += ly_print(out, ")");
+ }
+ break;
+ case LYS_IFF_AND:
+ case LYS_IFF_OR:
+ if (brackets_flag && op == LYS_IFF_AND) {
+ /* AND does not need brackets */
+ brackets_flag = 0;
+ }
+
+ if (brackets_flag) {
+ count += ly_print(out, "(");
+ }
+ count += write_iff(out, module, expr, index_e, index_f);
+ count += ly_print(out, " %s ", op == LYS_IFF_OR ? "or" : "and");
+ count += write_iff(out, module, expr, index_e, index_f);
+ if (brackets_flag) {
+ count += ly_print(out, ")");
+ }
+ }
+
+ return count;
+}
+
+int
+ly_print_iffeature(struct lyout *out, const struct lys_module *module, struct lys_iffeature *expr)
+{
+ int index_e = 0, index_f = 0;
+
+ if (expr->expr) {
+ return write_iff(out, module, expr, &index_e, &index_f);
+ }
+
+ return 0;
+}
+
+static int
lys_print_(struct lyout *out, const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node)
{
int ret;
diff --git a/src/printer.h b/src/printer.h
index 0df3080..cc67195 100644
--- a/src/printer.h
+++ b/src/printer.h
@@ -49,6 +49,7 @@
int ly_print(struct lyout *out, const char *format, ...);
void ly_print_flush(struct lyout *out);
int ly_write(struct lyout *out, const char *buf, size_t count);
+int ly_print_iffeature(struct lyout *out, const struct lys_module *module, struct lys_iffeature *expr);
int yang_print_model(struct lyout *out, const struct lys_module *module);
int yin_print_model(struct lyout *out, const struct lys_module *module);
diff --git a/src/printer_info.c b/src/printer_info.c
index 3fc027a..58b225e 100644
--- a/src/printer_info.c
+++ b/src/printer_info.c
@@ -151,16 +151,20 @@
}
static void
-info_print_if_feature(struct lyout *out, struct lys_feature ** const features, uint8_t features_size)
+info_print_if_feature(struct lyout *out, const struct lys_module *module,
+ struct lys_iffeature *iffeature, uint8_t iffeature_size)
{
int i;
ly_print(out, "%-*s", INDENT_LEN, "If-feats: ");
- if (features_size) {
- ly_print(out, "%s\n", features[0]->name);
- for (i = 1; i < features_size; ++i) {
- ly_print(out, "%*s%s\n", INDENT_LEN, "", features[i]->name);
+ if (iffeature_size) {
+ ly_print_iffeature(out, module, &iffeature[0]);
+ ly_print(out, "\n");
+ for (i = 1; i < iffeature_size; ++i) {
+ ly_print(out, "%*s", INDENT_LEN, "");
+ ly_print_iffeature(out, module, &iffeature[i]);
+ ly_print(out, "\n");
}
} else {
ly_print(out, "\n");
@@ -722,7 +726,7 @@
info_print_text(out, feat->dsc, "Desc: ");
info_print_text(out, feat->ref, "Reference: ");
info_print_flags(out, feat->flags, LYS_STATUS_MASK | LYS_FENABLED, 0);
- info_print_if_feature(out, feat->features, feat->features_size);
+ info_print_if_feature(out, feat->module, feat->iffeature, feat->iffeature_size);
}
static void
@@ -793,7 +797,7 @@
info_print_text(out, cont->ref, "Reference: ");
info_print_flags(out, cont->flags, LYS_CONFIG_MASK | LYS_STATUS_MASK | LYS_MAND_MASK, 0);
info_print_text(out, cont->presence, "Presence: ");
- info_print_if_feature(out, cont->features, cont->features_size);
+ info_print_if_feature(out, cont->module, cont->iffeature, cont->iffeature_size);
info_print_when(out, cont->when);
info_print_must(out, cont->must, cont->must_size);
info_print_typedef(out, cont->tpdf, cont->tpdf_size);
@@ -818,7 +822,7 @@
} else {
ly_print(out, "\n");
}
- info_print_if_feature(out, choice->features, choice->features_size);
+ info_print_if_feature(out, choice->module, choice->iffeature, choice->iffeature_size);
info_print_when(out, choice->when);
info_print_nacmext(out, choice->nacm);
@@ -838,7 +842,7 @@
info_print_text(out, leaf->type.der->name, "Type: ");
info_print_text(out, leaf->units, "Units: ");
info_print_text(out, leaf->dflt, "Default: ");
- info_print_if_feature(out, leaf->features, leaf->features_size);
+ info_print_if_feature(out, leaf->module, leaf->iffeature, leaf->iffeature_size);
info_print_when(out, leaf->when);
info_print_must(out, leaf->must, leaf->must_size);
info_print_nacmext(out, leaf->nacm);
@@ -857,7 +861,7 @@
info_print_text(out, llist->type.der->name, "Type: ");
info_print_text(out, llist->units, "Units: ");
info_print_list_constr(out, llist->min, llist->max);
- info_print_if_feature(out, llist->features, llist->features_size);
+ info_print_if_feature(out, llist->module, llist->iffeature, llist->iffeature_size);
info_print_when(out, llist->when);
info_print_must(out, llist->must, llist->must_size);
info_print_nacmext(out, llist->nacm);
@@ -874,7 +878,7 @@
info_print_text(out, list->ref, "Reference: ");
info_print_flags(out, list->flags, LYS_CONFIG_MASK | LYS_STATUS_MASK | LYS_MAND_MASK | LYS_USERORDERED, 1);
info_print_list_constr(out, list->min, list->max);
- info_print_if_feature(out, list->features, list->features_size);
+ info_print_if_feature(out, list->module, list->iffeature, list->iffeature_size);
info_print_when(out, list->when);
info_print_must(out, list->must, list->must_size);
info_print_keys(out, list->keys, list->keys_size);
@@ -895,7 +899,7 @@
info_print_text(out, axml->dsc, "Desc: ");
info_print_text(out, axml->ref, "Reference: ");
info_print_flags(out, axml->flags, LYS_CONFIG_MASK | LYS_STATUS_MASK | LYS_MAND_MASK, 0);
- info_print_if_feature(out, axml->features, axml->features_size);
+ info_print_if_feature(out, axml->module, axml->iffeature, axml->iffeature_size);
info_print_when(out, axml->when);
info_print_must(out, axml->must, axml->must_size);
info_print_nacmext(out, axml->nacm);
@@ -927,7 +931,7 @@
info_print_text(out, cas->dsc, "Desc: ");
info_print_text(out, cas->ref, "Reference: ");
info_print_flags(out, cas->flags, LYS_CONFIG_MASK | LYS_STATUS_MASK | LYS_MAND_MASK, 0);
- info_print_if_feature(out, cas->features, cas->features_size);
+ info_print_if_feature(out, cas->module, cas->iffeature, cas->iffeature_size);
info_print_when(out, cas->when);
info_print_nacmext(out, cas->nacm);
@@ -937,7 +941,7 @@
static void
info_print_input(struct lyout *out, const struct lys_node *node)
{
- struct lys_node_rpc_inout *input = (struct lys_node_rpc_inout *)node;
+ struct lys_node_inout *input = (struct lys_node_inout *)node;
assert(lys_parent(node) && lys_parent(node)->nodetype == LYS_RPC);
@@ -950,7 +954,7 @@
static void
info_print_output(struct lyout *out, const struct lys_node *node)
{
- struct lys_node_rpc_inout *output = (struct lys_node_rpc_inout *)node;
+ struct lys_node_inout *output = (struct lys_node_inout *)node;
assert(lys_parent(node) && lys_parent(node)->nodetype == LYS_RPC);
@@ -970,7 +974,7 @@
info_print_text(out, ntf->dsc, "Desc: ");
info_print_text(out, ntf->ref, "Reference: ");
info_print_flags(out, ntf->flags, LYS_STATUS_MASK, 0);
- info_print_if_feature(out, ntf->features, ntf->features_size);
+ info_print_if_feature(out, ntf->module, ntf->iffeature, ntf->iffeature_size);
info_print_typedef(out, ntf->tpdf, ntf->tpdf_size);
info_print_nacmext(out, ntf->nacm);
@@ -980,20 +984,37 @@
static void
info_print_rpc(struct lyout *out, const struct lys_node *node)
{
- struct lys_node_rpc *rpc = (struct lys_node_rpc *)node;
+ struct lys_node_rpc_action *rpc = (struct lys_node_rpc_action *)node;
ly_print(out, "%-*s%s\n", INDENT_LEN, "RPC: ", rpc->name);
ly_print(out, "%-*s%s\n", INDENT_LEN, "Module: ", rpc->module->name);
info_print_text(out, rpc->dsc, "Desc: ");
info_print_text(out, rpc->ref, "Reference: ");
info_print_flags(out, rpc->flags, LYS_STATUS_MASK, 0);
- info_print_if_feature(out, rpc->features, rpc->features_size);
+ info_print_if_feature(out, rpc->module, rpc->iffeature, rpc->iffeature_size);
info_print_typedef(out, rpc->tpdf, rpc->tpdf_size);
info_print_nacmext(out, rpc->nacm);
info_print_snode(out, (struct lys_node *)rpc, rpc->child, "Data:");
}
+static void
+info_print_action(struct lyout *out, const struct lys_node *node)
+{
+ struct lys_node_rpc_action *act = (struct lys_node_rpc_action *)node;
+
+ ly_print(out, "%-*s%s\n", INDENT_LEN, "Action: ", act->name);
+ ly_print(out, "%-*s%s\n", INDENT_LEN, "Module: ", act->module->name);
+ info_print_text(out, act->dsc, "Desc: ");
+ info_print_text(out, act->ref, "Reference: ");
+ info_print_flags(out, act->flags, LYS_STATUS_MASK, 0);
+ info_print_if_feature(out, act->module, act->iffeature, act->iffeature_size);
+ info_print_typedef(out, act->tpdf, act->tpdf_size);
+ info_print_nacmext(out, act->nacm);
+
+ info_print_snode(out, (struct lys_node *)act, act->child, "Data:");
+}
+
int
info_print_model(struct lyout *out, const struct lys_module *module, const char *target_node)
{
@@ -1129,6 +1150,9 @@
case LYS_RPC:
info_print_rpc(out, target);
break;
+ case LYS_ACTION:
+ info_print_action(out, target);
+ break;
case LYS_INPUT:
info_print_input(out, target);
break;
diff --git a/src/printer_tree.c b/src/printer_tree.c
index 4aaac6a..dbe46e0 100644
--- a/src/printer_tree.c
+++ b/src/printer_tree.c
@@ -39,7 +39,7 @@
/* has a following printed child */
LY_TREE_FOR((struct lys_node *)(including ? node : node->next), cur) {
- if (module->type && (cur->module != module)) {
+ if (module != lys_node_module(cur)) {
continue;
}
@@ -89,7 +89,7 @@
}
/* next is a node that will actually be printed */
- has_next = sibling_is_valid_child(node, 0, module);
+ has_next = sibling_is_valid_child(node, 0, lys_main_module(module));
if (has_next && !next_is_case) {
strcat(new_indent, "| ");
@@ -145,20 +145,21 @@
}
static void
-tree_print_features(struct lyout *out, const struct lys_feature **features, uint8_t features_size)
+tree_print_features(struct lyout *out, const struct lys_module *module,
+ struct lys_iffeature *iffeature, uint8_t iffeature_size)
{
int i;
- if (!features_size) {
+ if (!iffeature_size) {
return;
}
ly_print(out, " {");
- for (i = 0; i < features_size; i++) {
+ for (i = 0; i < iffeature_size; i++) {
if (i > 0) {
ly_print(out, ",");
}
- ly_print(out, "%s", features[i]->name);
+ ly_print_iffeature(out, module, &iffeature[i]);
}
ly_print(out, "}?");
}
@@ -223,7 +224,7 @@
ly_print(out, "%s%s", cont->name, (cont->presence ? "!" : ""));
- tree_print_features(out, (const struct lys_feature **)cont->features, cont->features_size);
+ tree_print_features(out, module, cont->iffeature, cont->iffeature_size);
ly_print(out, "\n");
@@ -238,7 +239,7 @@
continue;
}
tree_print_snode(out, module, level, new_indent, max_child_len, sub,
- LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYXML | LYS_USES,
+ LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYXML | LYS_USES | LYS_ACTION,
spec_config);
}
@@ -281,7 +282,7 @@
ly_print(out, " <%s>", choice->dflt->name);
}
- tree_print_features(out, (const struct lys_feature **)choice->features, choice->features_size);
+ tree_print_features(out, module, choice->iffeature, choice->iffeature_size);
ly_print(out, "\n");
@@ -322,7 +323,7 @@
ly_print(out, "%s)", cas->name);
- tree_print_features(out, (const struct lys_feature **)cas->features, cas->features_size);
+ tree_print_features(out, module, cas->iffeature, cas->iffeature_size);
ly_print(out, "\n");
@@ -379,7 +380,7 @@
ly_print(out, "%s%s%*sanyxml", anyxml->name, (anyxml->flags & LYS_MAND_TRUE ? " " : "?"),
3 + (int)((max_name_len - strlen(anyxml->name)) - prefix_len), " ");
- tree_print_features(out, (const struct lys_feature **)anyxml->features, anyxml->features_size);
+ tree_print_features(out, module, anyxml->iffeature, anyxml->iffeature_size);
ly_print(out, "\n");
}
@@ -437,7 +438,7 @@
ly_print(out, " <%s>", leaf->dflt);
}
- tree_print_features(out, (const struct lys_feature **)leaf->features, leaf->features_size);
+ tree_print_features(out, module, leaf->iffeature, leaf->iffeature_size);
ly_print(out, "\n");
}
@@ -471,7 +472,7 @@
tree_print_type(out, &leaflist->type);
- tree_print_features(out, (const struct lys_feature **)leaflist->features, leaflist->features_size);
+ tree_print_features(out, module, leaflist->iffeature, leaflist->iffeature_size);
ly_print(out, "\n");
}
@@ -512,7 +513,7 @@
ly_print(out, "%s%s", list->keys[i]->name, i + 1 < list->keys_size ? " " : "]");
}
- tree_print_features(out, (const struct lys_feature **)list->features, list->features_size);
+ tree_print_features(out, module, list->iffeature, list->iffeature_size);
ly_print(out, "\n");
@@ -527,7 +528,7 @@
continue;
}
tree_print_snode(out, module, level, new_indent, max_child_len, sub,
- LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ANYXML,
+ LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ANYXML | LYS_ACTION,
spec_config);
}
@@ -548,12 +549,12 @@
}
static void
-tree_print_rpc(struct lyout *out, const struct lys_module *module, int level, char *indent,
- const struct lys_node *node)
+tree_print_rpc_action(struct lyout *out, const struct lys_module *module, int level, char *indent,
+ const struct lys_node *node)
{
char *new_indent;
struct lys_node *sub;
- struct lys_node_rpc *rpc = (struct lys_node_rpc *)node;
+ struct lys_node_rpc_action *rpc = (struct lys_node_rpc_action *)node;
if (lys_is_disabled(node, 0)) {
return;
@@ -562,7 +563,7 @@
ly_print(out, "%s%s---x %s", indent,
(rpc->flags & LYS_STATUS_DEPRC ? "x" : (rpc->flags & LYS_STATUS_OBSLT ? "o" : "+")), rpc->name);
- tree_print_features(out, (const struct lys_feature **)rpc->features, rpc->features_size);
+ tree_print_features(out, module, rpc->iffeature, rpc->iffeature_size);
ly_print(out, "\n");
@@ -601,7 +602,7 @@
(notif->flags & LYS_STATUS_DEPRC ? "x" : (notif->flags & LYS_STATUS_OBSLT ? "o" : "+")),
notif->name);
- tree_print_features(out, (const struct lys_feature **)notif->features, notif->features_size);
+ tree_print_features(out, module, notif->iffeature, notif->iffeature_size);
ly_print(out, "\n");
@@ -670,6 +671,9 @@
case LYS_USES:
tree_print_uses(out, module, level, indent, max_name_len, node, spec_config);
break;
+ case LYS_ACTION:
+ tree_print_rpc_action(out, module, level, indent, node);
+ break;
case LYS_CASE:
/* a very special case of cases in an augment */
tree_print_case(out, module, level, indent, max_name_len, node, 0, spec_config);
@@ -760,7 +764,7 @@
break;
}
if (node->nodetype == LYS_RPC) {
- tree_print_rpc(out, module, level, indent, node);
+ tree_print_rpc_action(out, module, level, indent, node);
have_rpcs--;
}
}
diff --git a/src/printer_xml.c b/src/printer_xml.c
index 7e4478a..0146a22 100644
--- a/src/printer_xml.c
+++ b/src/printer_xml.c
@@ -378,6 +378,7 @@
switch (node->schema->nodetype) {
case LYS_NOTIF:
case LYS_RPC:
+ case LYS_ACTION:
case LYS_CONTAINER:
xml_print_container(out, level, node, toplevel);
break;
@@ -402,15 +403,42 @@
int
xml_print_data(struct lyout *out, const struct lyd_node *root, int options)
{
- const struct lyd_node *node;
+ const struct lyd_node *node, *next;
+ int level, action = 0;
+
+ assert(root);
+
+ level = (options & LYP_FORMAT ? 1 : 0);
+
+ /* learn whether we are printing an action first */
+ LY_TREE_DFS_BEGIN(root, next, node) {
+ if (node->schema->nodetype == LYS_ACTION) {
+ action = 1;
+ break;
+ }
+ LY_TREE_DFS_END(root, next, node);
+ }
+
+ if (action) {
+ ly_print(out, "%*s<action xmlns=\"urn:ietf:params:xml:ns:yang:1\">%s", LEVEL, INDENT, level ? "\n" : "");
+ if (level) {
+ ++level;
+ }
+ }
/* content */
LY_TREE_FOR(root, node) {
- xml_print_node(out, (options & LYP_FORMAT ? 1 : 0), node, 1);
+ xml_print_node(out, level, node, 1);
if (!(options & LYP_WITHSIBLINGS)) {
break;
}
}
+
+ if (action) {
+ --level;
+ ly_print(out, "%*s</action>%s", LEVEL, INDENT, level ? "\n" : "");
+ }
+
ly_print_flush(out);
return EXIT_SUCCESS;
diff --git a/src/printer_yang.c b/src/printer_yang.c
index afd1001..0ebc2d5 100644
--- a/src/printer_yang.c
+++ b/src/printer_yang.c
@@ -234,16 +234,11 @@
}
static void
-yang_print_iffeature(struct lyout *out, int level, const struct lys_module *module, const struct lys_feature *feat)
+yang_print_iffeature(struct lyout *out, int level, const struct lys_module *module, struct lys_iffeature *iffeature)
{
- struct lys_module *mod;
-
- ly_print(out, "%*sif-feature ", LEVEL, INDENT);
- mod = lys_main_module(feat->module);
- if (lys_main_module(module) != mod) {
- ly_print(out, "%s:", transform_module_name2import_prefix(module, mod->name));
- }
- ly_print(out, "%s;\n", feat->name);
+ ly_print(out, "%*sif-feature \"", LEVEL, INDENT);
+ ly_print_iffeature(out, module, iffeature);
+ ly_print(out, "\";\n");
}
static void
@@ -255,9 +250,9 @@
level++;
yang_print_snode_common(out, level, (struct lys_node *)feat, &flag);
- for (i = 0; i < feat->features_size; ++i) {
+ for (i = 0; i < feat->iffeature_size; ++i) {
yang_print_open(out, &flag);
- yang_print_iffeature(out, level, feat->module, feat->features[i]);
+ yang_print_iffeature(out, level, feat->module, &feat->iffeature[i]);
}
level--;
@@ -655,8 +650,8 @@
yang_print_nacmext(out, level, (struct lys_node *)augment, module, NULL);
yang_print_snode_common(out, level, (struct lys_node *)augment, NULL);
- for (i = 0; i < augment->features_size; i++) {
- yang_print_iffeature(out, level, module, augment->features[i]);
+ for (i = 0; i < augment->iffeature_size; i++) {
+ yang_print_iffeature(out, level, module, &augment->iffeature[i]);
}
if (augment->when) {
@@ -670,7 +665,7 @@
}
yang_print_snode(out, level, sub,
LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
- LYS_USES | LYS_ANYXML | LYS_CASE);
+ LYS_USES | LYS_ANYXML | LYS_CASE | LYS_ACTION);
}
level--;
@@ -738,9 +733,9 @@
yang_print_when(out, level, node->module, cont->when);
}
- for (i = 0; i < cont->features_size; i++) {
+ for (i = 0; i < cont->iffeature_size; i++) {
yang_print_open(out, &flag);
- yang_print_iffeature(out, level, node->module, cont->features[i]);
+ yang_print_iffeature(out, level, node->module, &cont->iffeature[i]);
}
for (i = 0; i < cont->must_size; i++) {
@@ -768,7 +763,7 @@
yang_print_open(out, &flag);
yang_print_snode(out, level, sub,
LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
- LYS_USES | LYS_GROUPING | LYS_ANYXML);
+ LYS_USES | LYS_GROUPING | LYS_ANYXML | LYS_ACTION);
}
level--;
@@ -787,8 +782,8 @@
yang_print_nacmext(out, level, node, node->module, NULL);
yang_print_snode_common2(out, level, node, NULL);
- for (i = 0; i < cas->features_size; i++) {
- yang_print_iffeature(out, level, node->module, cas->features[i]);
+ for (i = 0; i < cas->iffeature_size; i++) {
+ yang_print_iffeature(out, level, node->module, &cas->iffeature[i]);
}
if (cas->when) {
@@ -826,8 +821,8 @@
yang_print_snode_common2(out, level, node, NULL);
- for (i = 0; i < choice->features_size; i++) {
- yang_print_iffeature(out, level, node->module, choice->features[i]);
+ for (i = 0; i < choice->iffeature_size; i++) {
+ yang_print_iffeature(out, level, node->module, &choice->iffeature[i]);
}
if (choice->when) {
@@ -859,8 +854,8 @@
if (leaf->when) {
yang_print_when(out, level, node->module, leaf->when);
}
- for (i = 0; i < leaf->features_size; i++) {
- yang_print_iffeature(out, level, node->module, leaf->features[i]);
+ for (i = 0; i < leaf->iffeature_size; i++) {
+ yang_print_iffeature(out, level, node->module, &leaf->iffeature[i]);
}
for (i = 0; i < leaf->must_size; i++) {
yang_print_must(out, level, node->module, &leaf->must[i]);
@@ -888,9 +883,9 @@
level++;
yang_print_nacmext(out, level, node, node->module, &flag);
yang_print_snode_common2(out, level, node, &flag);
- for (i = 0; i < anyxml->features_size; i++) {
+ for (i = 0; i < anyxml->iffeature_size; i++) {
yang_print_open(out, &flag);
- yang_print_iffeature(out, level, node->module, anyxml->features[i]);
+ yang_print_iffeature(out, level, node->module, &anyxml->iffeature[i]);
}
for (i = 0; i < anyxml->must_size; i++) {
yang_print_open(out, &flag);
@@ -917,8 +912,8 @@
if (llist->when) {
yang_print_when(out, level, llist->module, llist->when);
}
- for (i = 0; i < llist->features_size; i++) {
- yang_print_iffeature(out, level, node->module, llist->features[i]);
+ for (i = 0; i < llist->iffeature_size; i++) {
+ yang_print_iffeature(out, level, node->module, &llist->iffeature[i]);
}
for (i = 0; i < llist->must_size; i++) {
yang_print_must(out, level, node->module, &llist->must[i]);
@@ -955,8 +950,8 @@
if (list->when) {
yang_print_when(out, level, list->module, list->when);
}
- for (i = 0; i < list->features_size; i++) {
- yang_print_iffeature(out, level, node->module, list->features[i]);
+ for (i = 0; i < list->iffeature_size; i++) {
+ yang_print_iffeature(out, level, node->module, &list->iffeature[i]);
}
for (i = 0; i < list->must_size; i++) {
yang_print_must(out, level, list->module, &list->must[i]);
@@ -992,7 +987,7 @@
}
yang_print_snode(out, level, sub,
LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
- LYS_USES | LYS_GROUPING | LYS_ANYXML);
+ LYS_USES | LYS_GROUPING | LYS_ANYXML | LYS_ACTION);
}
level--;
ly_print(out, "%*s}\n", LEVEL, INDENT);
@@ -1017,7 +1012,7 @@
LY_TREE_FOR(node->child, sub) {
yang_print_snode(out, level, sub,
LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
- LYS_USES | LYS_GROUPING | LYS_ANYXML);
+ LYS_USES | LYS_GROUPING | LYS_ANYXML | LYS_ACTION);
}
level--;
@@ -1043,9 +1038,9 @@
yang_print_nacmext(out, level, node, node->module, &flag);
yang_print_snode_common(out, level, node, &flag);
- for (i = 0; i < uses->features_size; i++) {
+ for (i = 0; i < uses->iffeature_size; i++) {
yang_print_open(out, &flag);
- yang_print_iffeature(out, level, node->module, uses->features[i]);
+ yang_print_iffeature(out, level, node->module, &uses->iffeature[i]);
}
if (uses->when) {
yang_print_open(out, &flag);
@@ -1071,7 +1066,7 @@
{
int i;
struct lys_node *sub;
- struct lys_node_rpc_inout *inout = (struct lys_node_rpc_inout *)node;
+ struct lys_node_inout *inout = (struct lys_node_inout *)node;
ly_print(out, "%*s%s {\n", LEVEL, INDENT, (inout->nodetype == LYS_INPUT ? "input" : "output"));
@@ -1095,20 +1090,20 @@
}
static void
-yang_print_rpc(struct lyout *out, int level, const struct lys_node *node)
+yang_print_rpc_action(struct lyout *out, int level, const struct lys_node *node)
{
int i, flag = 0;
struct lys_node *sub;
- struct lys_node_rpc *rpc = (struct lys_node_rpc *)node;
+ struct lys_node_rpc_action *rpc = (struct lys_node_rpc_action *)node;
- ly_print(out, "%*srpc %s", LEVEL, INDENT, node->name);
+ ly_print(out, "%*s%s %s", LEVEL, INDENT, (node->nodetype == LYS_RPC ? "rpc" : "action"), node->name);
level++;
yang_print_snode_common(out, level, node, &flag);
- for (i = 0; i < rpc->features_size; i++) {
+ for (i = 0; i < rpc->iffeature_size; i++) {
yang_print_open(out, &flag);
- yang_print_iffeature(out, level, node->module, rpc->features[i]);
+ yang_print_iffeature(out, level, node->module, &rpc->iffeature[i]);
}
for (i = 0; i < rpc->tpdf_size; i++) {
@@ -1141,9 +1136,9 @@
level++;
yang_print_snode_common(out, level, node, &flag);
- for (i = 0; i < notif->features_size; i++) {
+ for (i = 0; i < notif->iffeature_size; i++) {
yang_print_open(out, &flag);
- yang_print_iffeature(out, level, node->module, notif->features[i]);
+ yang_print_iffeature(out, level, node->module, ¬if->iffeature[i]);
}
for (i = 0; i < notif->tpdf_size; i++) {
@@ -1197,6 +1192,9 @@
case LYS_CASE:
yang_print_case(out, level, node);
break;
+ case LYS_ACTION:
+ yang_print_rpc_action(out, level, node);
+ break;
case LYS_INPUT:
case LYS_OUTPUT:
yang_print_input_output(out, level, node);
@@ -1337,7 +1335,7 @@
ly_print(out, "\n");
switch(node->nodetype) {
case LYS_RPC:
- yang_print_rpc(out, level, node);
+ yang_print_rpc_action(out, level, node);
break;
case LYS_NOTIF:
yang_print_notif(out, level, node);
diff --git a/src/printer_yin.c b/src/printer_yin.c
index 2f3e479..a36a2c0 100644
--- a/src/printer_yin.c
+++ b/src/printer_yin.c
@@ -221,16 +221,11 @@
}
static void
-yin_print_iffeature(struct lyout *out, int level, const struct lys_module *module, const struct lys_feature *feat)
+yin_print_iffeature(struct lyout *out, int level, const struct lys_module *module, struct lys_iffeature *iffeature)
{
- struct lys_module *mod;
-
ly_print(out, "%*s<if-feature name=\"", LEVEL, INDENT);
- mod = lys_main_module(feat->module);
- if (lys_main_module(module) != mod) {
- ly_print(out, "%s:", transform_module_name2import_prefix(module, mod->name));
- }
- ly_print(out, "%s\"/>\n", feat->name);
+ ly_print_iffeature(out, module, iffeature);
+ ly_print(out, "\"/>\n");
}
static void
@@ -238,15 +233,15 @@
{
int i, close;
- close = (yin_has_snode_common((struct lys_node *)feat) || feat->features_size ? 0 : 1);
+ close = (yin_has_snode_common((struct lys_node *)feat) || feat->iffeature_size ? 0 : 1);
yin_print_open(out, level, "feature", "name", feat->name, close);
if (!close) {
level++;
yin_print_snode_common(out, level, (struct lys_node *)feat);
- for (i = 0; i < feat->features_size; ++i) {
- yin_print_iffeature(out, level, feat->module, feat->features[i]);
+ for (i = 0; i < feat->iffeature_size; ++i) {
+ yin_print_iffeature(out, level, feat->module, &feat->iffeature[i]);
}
level--;
@@ -672,8 +667,8 @@
yin_print_nacmext(out, level, (struct lys_node *)augment, module);
yin_print_snode_common(out, level, (struct lys_node *)augment);
- for (i = 0; i < augment->features_size; i++) {
- yin_print_iffeature(out, level, module, augment->features[i]);
+ for (i = 0; i < augment->iffeature_size; i++) {
+ yin_print_iffeature(out, level, module, &augment->iffeature[i]);
}
if (augment->when) {
@@ -687,7 +682,7 @@
}
yin_print_snode(out, level, sub,
LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
- LYS_USES | LYS_ANYXML | LYS_CASE);
+ LYS_USES | LYS_ANYXML | LYS_CASE | LYS_ACTION);
}
level--;
@@ -756,8 +751,8 @@
yin_print_when(out, level, node->module, cont->when);
}
- for (i = 0; i < cont->features_size; i++) {
- yin_print_iffeature(out, level, node->module, cont->features[i]);
+ for (i = 0; i < cont->iffeature_size; i++) {
+ yin_print_iffeature(out, level, node->module, &cont->iffeature[i]);
}
for (i = 0; i < cont->must_size; i++) {
@@ -781,7 +776,7 @@
}
yin_print_snode(out, level, sub,
LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
- LYS_USES | LYS_GROUPING | LYS_ANYXML);
+ LYS_USES | LYS_GROUPING | LYS_ANYXML | LYS_ACTION);
}
level--;
@@ -801,8 +796,8 @@
yin_print_nacmext(out, level, node, node->module);
yin_print_snode_common2(out, level, node);
- for (i = 0; i < cas->features_size; i++) {
- yin_print_iffeature(out, level, node->module, cas->features[i]);
+ for (i = 0; i < cas->iffeature_size; i++) {
+ yin_print_iffeature(out, level, node->module, &cas->iffeature[i]);
}
if (cas->when) {
@@ -840,8 +835,8 @@
yin_print_snode_common2(out, level, node);
- for (i = 0; i < choice->features_size; i++) {
- yin_print_iffeature(out, level, node->module, choice->features[i]);
+ for (i = 0; i < choice->iffeature_size; i++) {
+ yin_print_iffeature(out, level, node->module, &choice->iffeature[i]);
}
if (choice->when) {
@@ -874,8 +869,8 @@
if (leaf->when) {
yin_print_when(out, level, node->module, leaf->when);
}
- for (i = 0; i < leaf->features_size; i++) {
- yin_print_iffeature(out, level, node->module, leaf->features[i]);
+ for (i = 0; i < leaf->iffeature_size; i++) {
+ yin_print_iffeature(out, level, node->module, &leaf->iffeature[i]);
}
for (i = 0; i < leaf->must_size; i++) {
yin_print_must(out, level, node->module, &leaf->must[i]);
@@ -899,7 +894,7 @@
int i, close;
struct lys_node_anyxml *anyxml = (struct lys_node_anyxml *)node;
- close = (yin_has_nacmext(node) || yin_has_snode_common2(node) || anyxml->features_size || anyxml->must_size
+ close = (yin_has_nacmext(node) || yin_has_snode_common2(node) || anyxml->iffeature_size || anyxml->must_size
|| anyxml->when ? 0 : 1);
yin_print_open(out, level, "anyxml", "name", anyxml->name, close);
@@ -908,8 +903,8 @@
level++;
yin_print_nacmext(out, level, node, node->module);
yin_print_snode_common2(out, level, node);
- for (i = 0; i < anyxml->features_size; i++) {
- yin_print_iffeature(out, level, node->module, anyxml->features[i]);
+ for (i = 0; i < anyxml->iffeature_size; i++) {
+ yin_print_iffeature(out, level, node->module, &anyxml->iffeature[i]);
}
for (i = 0; i < anyxml->must_size; i++) {
yin_print_must(out, level, node->module, &anyxml->must[i]);
@@ -936,8 +931,8 @@
if (llist->when) {
yin_print_when(out, level, llist->module, llist->when);
}
- for (i = 0; i < llist->features_size; i++) {
- yin_print_iffeature(out, level, node->module, llist->features[i]);
+ for (i = 0; i < llist->iffeature_size; i++) {
+ yin_print_iffeature(out, level, node->module, &llist->iffeature[i]);
}
for (i = 0; i < llist->must_size; i++) {
yin_print_must(out, level, node->module, &llist->must[i]);
@@ -975,8 +970,8 @@
if (list->when) {
yin_print_when(out, level, list->module, list->when);
}
- for (i = 0; i < list->features_size; i++) {
- yin_print_iffeature(out, level, node->module, list->features[i]);
+ for (i = 0; i < list->iffeature_size; i++) {
+ yin_print_iffeature(out, level, node->module, &list->iffeature[i]);
}
for (i = 0; i < list->must_size; i++) {
yin_print_must(out, level, list->module, &list->must[i]);
@@ -1012,7 +1007,7 @@
}
yin_print_snode(out, level, sub,
LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
- LYS_USES | LYS_GROUPING | LYS_ANYXML);
+ LYS_USES | LYS_GROUPING | LYS_ANYXML | LYS_ACTION);
}
level--;
@@ -1038,7 +1033,7 @@
LY_TREE_FOR(node->child, sub) {
yin_print_snode(out, level, sub,
LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
- LYS_USES | LYS_GROUPING | LYS_ANYXML);
+ LYS_USES | LYS_GROUPING | LYS_ANYXML | LYS_ACTION);
}
level--;
@@ -1052,7 +1047,7 @@
struct lys_node_uses *uses = (struct lys_node_uses *)node;
struct lys_module *mod;
- close = (yin_has_nacmext(node) || yin_has_snode_common(node) || uses->features_size || uses->when
+ close = (yin_has_nacmext(node) || yin_has_snode_common(node) || uses->iffeature_size || uses->when
|| uses->refine_size || uses->augment_size ? 0 : 1);
ly_print(out, "%*s<uses name=\"", LEVEL, INDENT);
@@ -1068,8 +1063,8 @@
level++;
yin_print_nacmext(out, level, node, node->module);
yin_print_snode_common(out, level, node);
- for (i = 0; i < uses->features_size; i++) {
- yin_print_iffeature(out, level, node->module, uses->features[i]);
+ for (i = 0; i < uses->iffeature_size; i++) {
+ yin_print_iffeature(out, level, node->module, &uses->iffeature[i]);
}
if (uses->when) {
yin_print_when(out, level, node->module, uses->when);
@@ -1093,7 +1088,7 @@
{
int i;
struct lys_node *sub;
- struct lys_node_rpc_inout *inout = (struct lys_node_rpc_inout *)node;
+ struct lys_node_inout *inout = (struct lys_node_inout *)node;
ly_print(out, "%*s<%s>\n", LEVEL, INDENT, (inout->nodetype == LYS_INPUT ? "input" : "output"));
@@ -1117,22 +1112,22 @@
}
static void
-yin_print_rpc(struct lyout *out, int level, const struct lys_node *node)
+yin_print_rpc_action(struct lyout *out, int level, const struct lys_node *node)
{
int i, close;
struct lys_node *sub;
- struct lys_node_rpc *rpc = (struct lys_node_rpc *)node;
+ struct lys_node_rpc_action *rpc = (struct lys_node_rpc_action *)node;
- close = (yin_has_snode_common(node) || rpc->features_size || rpc->tpdf_size || node->child ? 0 : 1);
+ close = (yin_has_snode_common(node) || rpc->iffeature_size || rpc->tpdf_size || node->child ? 0 : 1);
- yin_print_open(out, level, "rpc", "name", node->name, close);
+ yin_print_open(out, level, (node->nodetype == LYS_RPC ? "rpc" : "action"), "name", node->name, close);
if (!close) {
level++;
yin_print_snode_common(out, level, node);
- for (i = 0; i < rpc->features_size; i++) {
- yin_print_iffeature(out, level, node->module, rpc->features[i]);
+ for (i = 0; i < rpc->iffeature_size; i++) {
+ yin_print_iffeature(out, level, node->module, &rpc->iffeature[i]);
}
for (i = 0; i < rpc->tpdf_size; i++) {
@@ -1148,7 +1143,7 @@
}
level--;
- yin_print_close(out, level, "rpc");
+ yin_print_close(out, level, (node->nodetype == LYS_RPC ? "rpc" : "action"));
}
}
@@ -1159,7 +1154,7 @@
struct lys_node *sub;
struct lys_node_notif *notif = (struct lys_node_notif *)node;
- close = (yin_has_snode_common(node) || notif->features_size || notif->tpdf_size || node->child ? 0 : 1);
+ close = (yin_has_snode_common(node) || notif->iffeature_size || notif->tpdf_size || node->child ? 0 : 1);
yin_print_open(out, level, "notification", "name", node->name, close);
@@ -1167,8 +1162,8 @@
level++;
yin_print_snode_common(out, level, node);
- for (i = 0; i < notif->features_size; i++) {
- yin_print_iffeature(out, level, node->module, notif->features[i]);
+ for (i = 0; i < notif->iffeature_size; i++) {
+ yin_print_iffeature(out, level, node->module, ¬if->iffeature[i]);
}
for (i = 0; i < notif->tpdf_size; i++) {
@@ -1221,6 +1216,9 @@
case LYS_CASE:
yin_print_case(out, level, node);
break;
+ case LYS_ACTION:
+ yin_print_rpc_action(out, level, node);
+ break;
case LYS_INPUT:
case LYS_OUTPUT:
yin_print_input_output(out, level, node);
@@ -1390,7 +1388,7 @@
switch (node->nodetype) {
case LYS_RPC:
- yin_print_rpc(out, level, node);
+ yin_print_rpc_action(out, level, node);
break;
case LYS_NOTIF:
yin_print_notif(out, level, node);
diff --git a/src/resolve.c b/src/resolve.c
index 2711f52..cf27b89 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -955,6 +955,448 @@
}
/**
+ * @brief Resolve (find) a feature definition. Logs directly.
+ *
+ * @param[in] feat_name Feature name to resolve.
+ * @param[in] len Length of \p feat_name.
+ * @param[in] node Node with the if-feature expression.
+ * @param[out] feature Pointer to be set to point to the feature definition, if feature not found
+ * (return code 1), the pointer is untouched.
+ *
+ * @return 0 on success, 1 on forward reference, -1 on error.
+ */
+static int
+resolve_feature(const char *feat_name, uint16_t len, const struct lys_node *node, struct lys_feature **feature)
+{
+ char *str;
+ const char *mod_name, *name;
+ int mod_name_len, nam_len, i, j;
+ const struct lys_module *module;
+
+ assert(feature);
+
+ /* check prefix */
+ if ((i = parse_node_identifier(feat_name, &mod_name, &mod_name_len, &name, &nam_len)) < 1) {
+ LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, feat_name[-i], &feat_name[-i]);
+ return -1;
+ }
+
+ module = lys_get_import_module(lys_node_module(node), NULL, 0, mod_name, mod_name_len);
+ if (!module) {
+ /* identity refers unknown data model */
+ LOGVAL(LYE_INMOD_LEN, LY_VLOG_NONE, NULL, mod_name_len, mod_name);
+ return -1;
+ }
+
+ if (module != node->module && module == lys_node_module(node)) {
+ /* first, try to search directly in submodule where the feature was mentioned */
+ for (j = 0; j < node->module->features_size; j++) {
+ if (!strncmp(name, node->module->features[j].name, nam_len) && !node->module->features[j].name[nam_len]) {
+ /* check status */
+ if (lyp_check_status(node->flags, lys_node_module(node), node->name, node->module->features[j].flags,
+ node->module->features[j].module, node->module->features[j].name, node)) {
+ return -1;
+ }
+ *feature = &node->module->features[j];
+ return 0;
+ }
+ }
+ }
+
+ /* search in the identified module ... */
+ for (j = 0; j < module->features_size; j++) {
+ if (!strncmp(name, module->features[j].name, nam_len) && !module->features[j].name[nam_len]) {
+ /* check status */
+ if (lyp_check_status(node->flags, lys_node_module(node), node->name, module->features[j].flags,
+ module->features[j].module, module->features[j].name, node)) {
+ return -1;
+ }
+ *feature = &module->features[j];
+ return 0;
+ }
+ }
+ /* ... and all its submodules */
+ for (i = 0; i < module->inc_size; i++) {
+ if (!module->inc[i].submodule) {
+ /* not yet resolved */
+ continue;
+ }
+ for (j = 0; j < module->inc[i].submodule->features_size; j++) {
+ if (!strncmp(name, module->inc[i].submodule->features[j].name, nam_len)
+ && !module->inc[i].submodule->features[j].name[nam_len]) {
+ /* check status */
+ if (lyp_check_status(node->flags, lys_node_module(node), node->name,
+ module->inc[i].submodule->features[j].flags,
+ module->inc[i].submodule->features[j].module,
+ module->inc[i].submodule->features[j].name, node)) {
+ return -1;
+ }
+ *feature = &module->inc[i].submodule->features[j];
+ return 0;
+ }
+ }
+ }
+
+ /* not found */
+ str = strndup(feat_name, len);
+ LOGVAL(LYE_INRESOLV, LY_VLOG_NONE, NULL, "feature", str);
+ free(str);
+ return 1;
+}
+
+/*
+ * @return
+ * - 0 if enabled
+ * - 1 if disabled
+ * - -1 if not usable by its if-feature expression
+ */
+static int
+resolve_feature_value(const struct lys_feature *feat)
+{
+ int i;
+
+ for (i = 0; i < feat->iffeature_size; i++) {
+ if (resolve_iffeature(&feat->iffeature[i])) {
+ return -1;
+ }
+ }
+
+ return feat->flags & LYS_FENABLED ? 0 : 1;
+}
+
+static int
+resolve_iffeature_recursive(struct lys_iffeature *expr, int *index_e, int *index_f)
+{
+ uint8_t op;
+ int rc, a, b;
+
+ op = iff_getop(expr->expr, *index_e);
+ (*index_e)++;
+
+ switch (op) {
+ case LYS_IFF_F:
+ /* resolve feature */
+ return resolve_feature_value(expr->features[(*index_f)++]);
+ case LYS_IFF_NOT:
+ rc = resolve_iffeature_recursive(expr, index_e, index_f);
+ if (rc == -1) {
+ /* one of the referenced feature is hidden by its if-feature,
+ * so this if-feature expression is always false */
+ return -1;
+ } else {
+ /* invert result */
+ return rc ? 0 : 1;
+ }
+ case LYS_IFF_AND:
+ case LYS_IFF_OR:
+ a = resolve_iffeature_recursive(expr, index_e, index_f);
+ b = resolve_iffeature_recursive(expr, index_e, index_f);
+ if (a == -1 || b == -1) {
+ /* one of the referenced feature is hidden by its if-feature,
+ * so this if-feature expression is always false */
+ return -1;
+ } else if (op == LYS_IFF_AND) {
+ return a && b;
+ } else { /* LYS_IFF_OR */
+ return a || b;
+ }
+ }
+
+ return -1;
+}
+
+int
+resolve_iffeature(struct lys_iffeature *expr)
+{
+ int rc = -1;
+ int index_e = 0, index_f = 0;
+
+ if (expr->expr) {
+ rc = resolve_iffeature_recursive(expr, &index_e, &index_f);
+ }
+ return (rc == 0) ? 0 : 1;
+}
+
+struct iff_stack {
+ int size;
+ int index; /* first empty item */
+ uint8_t *stack;
+};
+
+static int
+iff_stack_push(struct iff_stack *stack, uint8_t value)
+{
+ if (stack->index == stack->size) {
+ stack->size += 4;
+ stack->stack = ly_realloc(stack->stack, stack->size * sizeof *stack->stack);
+ if (!stack->stack) {
+ LOGMEM;
+ stack->size = 0;
+ return EXIT_FAILURE;
+ }
+ }
+
+ stack->stack[stack->index++] = value;
+ return EXIT_SUCCESS;
+}
+
+static uint8_t
+iff_stack_pop(struct iff_stack *stack)
+{
+ stack->index--;
+ return stack->stack[stack->index];
+}
+
+static void
+iff_stack_clean(struct iff_stack *stack)
+{
+ stack->size = 0;
+ free(stack->stack);
+}
+
+static void
+iff_setop(uint8_t *list, uint8_t op, int pos)
+{
+ uint8_t *item;
+ uint8_t mask = 3;
+
+ assert(pos >= 0);
+ assert(op <= 3); /* max 2 bits */
+
+ item = &list[pos / 4];
+ mask = mask << 2 * (pos % 4);
+ *item = (*item) & ~mask;
+ *item = (*item) | (op << 2 * (pos % 4));
+}
+
+uint8_t
+iff_getop(uint8_t *list, int pos)
+{
+ uint8_t *item;
+ uint8_t mask = 3, result;
+
+ assert(pos >= 0);
+
+ item = &list[pos / 4];
+ result = (*item) & (mask << 2 * (pos % 4));
+ return result >> 2 * (pos % 4);
+}
+
+#define LYS_IFF_LP 0x04 /* ( */
+#define LYS_IFF_RP 0x08 /* ) */
+
+void
+resolve_iffeature_getsizes(struct lys_iffeature *iffeat, unsigned int *expr_size, unsigned int *feat_size)
+{
+ unsigned int e = 0, f = 0, r = 0;
+ uint8_t op;
+
+ assert(iffeat);
+
+ if (!iffeat->expr) {
+ goto result;
+ }
+
+ do {
+ op = iff_getop(iffeat->expr, e++);
+ switch (op) {
+ case LYS_IFF_NOT:
+ if (!r) {
+ r += 1;
+ }
+ break;
+ case LYS_IFF_AND:
+ case LYS_IFF_OR:
+ if (!r) {
+ r += 2;
+ } else {
+ r += 1;
+ }
+ break;
+ case LYS_IFF_F:
+ f++;
+ if (r) {
+ r--;
+ }
+ break;
+ }
+ } while(r);
+
+result:
+ if (expr_size) {
+ *expr_size = e;
+ }
+ if (feat_size) {
+ *feat_size = f;
+ }
+}
+
+int
+resolve_iffeature_compile(struct lys_iffeature *iffeat_expr, const char *value, struct lys_node *node,
+ struct unres_schema *unres)
+{
+ const char *c = value;
+ int r, rc = EXIT_FAILURE;
+ int i, j, last_not;
+ unsigned int f_size = 0, expr_size = 0;
+ uint8_t op;
+ struct iff_stack stack = {0, 0, NULL};
+
+ assert(c);
+
+ if (isspace(c[0])) {
+ LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, c[0], c);
+ return EXIT_FAILURE;
+ }
+
+ /* pre-parse the expression to get sizes for arrays, also do some syntax checks of the expression */
+ for (i = j = last_not = 0; c[i]; i++) {
+ if (c[i] == '(') {
+ j++;
+ continue;
+ } else if (c[i] == ')') {
+ j--;
+ continue;
+ } else if (isspace(c[i])) {
+ continue;
+ }
+
+ if (!strncmp(&c[i], "not", r = 3) || !strncmp(&c[i], "and", r = 3) || !strncmp(&c[i], "or", r = 2)) {
+ if (c[i + r] == '\0') {
+ LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, c[i], c);
+ return EXIT_FAILURE;
+ } else if (!isspace(c[i + r])) {
+ /* feature name starting with the not/and/or */
+ last_not = 0;
+ f_size++;
+ } else if (c[i] == 'n') { /* not operation */
+ if (last_not) {
+ /* double not */
+ expr_size = expr_size - 2;
+ last_not = 0;
+ } else {
+ last_not = 1;
+ }
+ } else {
+ /* not a not operation */
+ last_not = 0;
+ }
+ i += r;
+ } else {
+ f_size++;
+ last_not = 0;
+ }
+ expr_size++;
+
+ while (!isspace(c[i])) {
+ if (!c[i] || c[i] == ')') {
+ i--;
+ break;
+ }
+ i++;
+ }
+ }
+ if (j) {
+ /* not matching count of ( and ) */
+ LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
+ return EXIT_FAILURE;
+ }
+
+ /* allocate the memory */
+ iffeat_expr->expr = calloc((j = (expr_size / 4) + ((expr_size % 4) ? 1 : 0)), sizeof *iffeat_expr->expr);
+ iffeat_expr->features = malloc(f_size * sizeof *iffeat_expr->features);
+ stack.size = expr_size;
+ stack.stack = malloc(expr_size * sizeof *stack.stack);
+ if (!stack.stack || !iffeat_expr->expr || !iffeat_expr->features) {
+ LOGMEM;
+ goto error;
+ }
+ f_size--; expr_size--; /* used as indexes from now */
+
+ for (i--; i >= 0; i--) {
+ if (c[i] == ')') {
+ /* push it on stack */
+ iff_stack_push(&stack, LYS_IFF_RP);
+ continue;
+ } else if (c[i] == '(') {
+ /* pop from the stack into result all operators until ) */
+ while((op = iff_stack_pop(&stack)) != LYS_IFF_RP) {
+ iff_setop(iffeat_expr->expr, op, expr_size--);
+ }
+ continue;
+ } else if (isspace(c[i])) {
+ continue;
+ }
+
+ /* end operator or operand -> find beginning and get what is it */
+ j = i + 1;
+ while (i >= 0 && !isspace(c[i]) && c[i] != '(') {
+ i--;
+ }
+ i++; /* get back by one step */
+
+ if (!strncmp(&c[i], "not ", 4)) {
+ if (stack.index && stack.stack[stack.index - 1] == LYS_IFF_NOT) {
+ /* double not */
+ iff_stack_pop(&stack);
+ } else {
+ /* not has the highest priority, so do not pop from the stack
+ * as in case of AND and OR */
+ iff_stack_push(&stack, LYS_IFF_NOT);
+ }
+ } else if (!strncmp(&c[i], "and ", 4)) {
+ /* as for OR - pop from the stack all operators with the same or higher
+ * priority and store them to the result, then push the AND to the stack */
+ while (stack.index && stack.stack[stack.index - 1] <= LYS_IFF_AND) {
+ op = iff_stack_pop(&stack);
+ iff_setop(iffeat_expr->expr, op, expr_size--);
+ }
+ iff_stack_push(&stack, LYS_IFF_AND);
+ } else if (!strncmp(&c[i], "or ", 3)) {
+ while (stack.index && stack.stack[stack.index - 1] <= LYS_IFF_OR) {
+ op = iff_stack_pop(&stack);
+ iff_setop(iffeat_expr->expr, op, expr_size--);
+ }
+ iff_stack_push(&stack, LYS_IFF_OR);
+ } else {
+ /* feature name, length is j - i */
+
+ /* add it to the result */
+ iff_setop(iffeat_expr->expr, LYS_IFF_F, expr_size--);
+
+ /* now get the link to the feature definition. Since it can be
+ * forward referenced, we have hack for unres - until resolved,
+ * the feature name is stored instead of link to the lys_feature */
+ iffeat_expr->features[f_size] = (void*)strndup(&c[i], j - i);
+ r = unres_schema_add_node(node->module, unres, &iffeat_expr->features[f_size], UNRES_IFFEAT, node);
+ f_size--;
+
+ if (r == -1) {
+ goto error;
+ }
+ }
+ }
+ while (stack.index) {
+ op = iff_stack_pop(&stack);
+ iff_setop(iffeat_expr->expr, op, expr_size--);
+ }
+
+ if (++expr_size || ++f_size) {
+ /* not all expected operators and operands found */
+ LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
+ rc = EXIT_FAILURE;
+ } else {
+ rc = EXIT_SUCCESS;
+ }
+
+error:
+ /* cleanup */
+ iff_stack_clean(&stack);
+
+ return rc;
+}
+
+/**
* @brief Resolve (find) a data node based on a schema-nodeid.
*
* Used for resolving unique statements - so id is expected to be relative and local (without reference to a different
@@ -2237,8 +2679,9 @@
break;
case LYS_RPC:
- tpdf_size = ((struct lys_node_rpc *)parent)->tpdf_size;
- tpdf = ((struct lys_node_rpc *)parent)->tpdf;
+ case LYS_ACTION:
+ tpdf_size = ((struct lys_node_rpc_action *)parent)->tpdf_size;
+ tpdf = ((struct lys_node_rpc_action *)parent)->tpdf;
break;
case LYS_NOTIF:
@@ -2248,8 +2691,8 @@
case LYS_INPUT:
case LYS_OUTPUT:
- tpdf_size = ((struct lys_node_rpc_inout *)parent)->tpdf_size;
- tpdf = ((struct lys_node_rpc_inout *)parent)->tpdf;
+ tpdf_size = ((struct lys_node_inout *)parent)->tpdf_size;
+ tpdf = ((struct lys_node_inout *)parent)->tpdf;
break;
default:
@@ -2501,82 +2944,6 @@
return rc;
}
-/**
- * @brief Resolve (find) a feature definition. Logs directly.
- *
- * @param[in] name Feature name.
- * @param[in] module Module to search in.
- * @param[out] ret Pointer to the resolved feature. Can be NULL.
- *
- * @return EXIT_SUCCESS on success, EXIT_FAILURE on forward reference, -1 on error.
- */
-static int
-resolve_feature(const char *id, const struct lys_module *module, struct lys_feature **ret)
-{
- const char *mod_name, *name;
- int mod_name_len, nam_len, i, j;
- struct lys_node *node;
-
- assert(id);
- assert(module);
-
- /* check prefix */
- if ((i = parse_node_identifier(id, &mod_name, &mod_name_len, &name, &nam_len)) < 1) {
- LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, id[-i], &id[-i]);
- return -1;
- }
-
- module = lys_get_import_module(module, NULL, 0, mod_name, mod_name_len);
- if (!module) {
- /* identity refers unknown data model */
- LOGVAL(LYE_INMOD_LEN, LY_VLOG_NONE, NULL, mod_name_len, mod_name);
- return -1;
- }
-
- /* search in the identified module ... */
- for (j = 0; j < module->features_size; j++) {
- if (!strcmp(name, module->features[j].name)) {
- if (ret) {
- /* check status */
- node = (struct lys_node *)*ret;
- if (lyp_check_status(node->flags, node->module, node->name, module->features[j].flags,
- module->features[j].module, module->features[j].name, node)) {
- return -1;
- }
- *ret = &module->features[j];
- }
- return EXIT_SUCCESS;
- }
- }
- /* ... and all its submodules */
- for (i = 0; i < module->inc_size; i++) {
- if (!module->inc[i].submodule) {
- /* not yet resolved */
- continue;
- }
- for (j = 0; j < module->inc[i].submodule->features_size; j++) {
- if (!strcmp(name, module->inc[i].submodule->features[j].name)) {
- if (ret) {
- /* check status */
- node = (struct lys_node *)*ret;
- if (lyp_check_status(node->flags, node->module, node->name,
- module->inc[i].submodule->features[j].flags,
- module->inc[i].submodule->features[j].module,
- module->inc[i].submodule->features[j].name, node)) {
- return -1;
- }
- *ret = &(module->inc[i].submodule->features[j]);
- }
- return EXIT_SUCCESS;
- }
- }
- }
-
- /* not found */
- LOGVAL(LYE_INRESOLV, LY_VLOG_NONE, NULL, "feature", id);
- return EXIT_FAILURE;
-}
-
void
unres_data_del(struct unres_data *unres, uint32_t i)
{
@@ -4481,31 +4848,31 @@
resolve_unres_schema_item(struct lys_module *mod, void *item, enum UNRES_ITEM type, void *str_snode,
struct unres_schema *unres)
{
+ /* has_str - whether the str_snode is a string in a dictionary that needs to be freed */
int rc = -1, has_str = 0, tpdf_flag = 0;
struct lys_node *node;
- const char *base_name;
+ const char *expr;
struct lys_ident *ident;
struct lys_type *stype;
- struct lys_feature **feat_ptr;
struct lys_node_choice *choic;
struct lyxml_elem *yin;
struct yang_type *yang;
switch (type) {
case UNRES_IDENT:
- base_name = str_snode;
+ expr = str_snode;
has_str = 1;
ident = item;
- rc = resolve_base_ident(mod, ident, base_name, "identity", NULL);
+ rc = resolve_base_ident(mod, ident, expr, "identity", NULL);
break;
case UNRES_TYPE_IDENTREF:
- base_name = str_snode;
+ expr = str_snode;
has_str = 1;
stype = item;
- rc = resolve_base_ident(mod, NULL, base_name, "type", stype);
+ rc = resolve_base_ident(mod, NULL, expr, "type", stype);
break;
case UNRES_TYPE_LEAFREF:
node = str_snode;
@@ -4571,28 +4938,31 @@
}
break;
case UNRES_IFFEAT:
- base_name = str_snode;
- has_str = 1;
- feat_ptr = item;
+ node = str_snode;
+ expr = *((const char **)item);
- rc = resolve_feature(base_name, mod, feat_ptr);
+ rc = resolve_feature(expr, strlen(expr), node, item);
+ if (!rc) {
+ /* success */
+ free((char *)expr);
+ }
break;
case UNRES_USES:
rc = resolve_unres_schema_uses(item, unres);
break;
case UNRES_TYPE_DFLT:
- base_name = str_snode;
+ expr = str_snode;
has_str = 1;
stype = item;
- rc = check_default(stype, base_name, mod);
+ rc = check_default(stype, expr, mod);
break;
case UNRES_CHOICE_DFLT:
- base_name = str_snode;
+ expr = str_snode;
has_str = 1;
choic = item;
- choic->dflt = resolve_choice_dflt(choic, base_name);
+ choic->dflt = resolve_choice_dflt(choic, expr);
if (choic->dflt) {
rc = EXIT_SUCCESS;
} else {
@@ -4660,7 +5030,7 @@
LOGVRB("Resolving %s \"%s\" failed, it will be attempted later.", "derived type", type_name);
break;
case UNRES_IFFEAT:
- LOGVRB("Resolving %s \"%s\" failed, it will be attempted later.", "if-feature", (char *)str_node);
+ LOGVRB("Resolving %s \"%s\" failed, it will be attempted later.", "if-feature", (char *)item);
break;
case UNRES_USES:
LOGVRB("Resolving %s \"%s\" failed, it will be attempted later.", "uses", ((struct lys_node_uses *)item)->name);
@@ -4899,7 +5269,7 @@
* @param[in] type Type of the old unresolved item.
* @param[in] new_item New item to use in the duplicate.
*
- * @return EXIT_SUCCESS on success, -1 on error.
+ * @return EXIT_SUCCESS on success, EXIT_FAILURE if item is not in unres, -1 on error.
*/
int
unres_schema_dup(struct lys_module *mod, struct unres_schema *unres, void *item, enum UNRES_ITEM type, void *new_item)
@@ -4911,10 +5281,10 @@
i = unres_schema_find(unres, item, type);
if (i == -1) {
- return -1;
+ return EXIT_FAILURE;
}
- if ((type == UNRES_TYPE_LEAFREF) || (type == UNRES_USES) || (type == UNRES_TYPE_DFLT)) {
+ if ((type == UNRES_TYPE_LEAFREF) || (type == UNRES_USES) || (type == UNRES_TYPE_DFLT) || (type == UNRES_IFFEAT)) {
if (unres_schema_add_node(mod, unres, new_item, type, unres->str_snode[i]) == -1) {
LOGINT;
return -1;
@@ -4965,7 +5335,6 @@
break;
case UNRES_IDENT:
case UNRES_TYPE_IDENTREF:
- case UNRES_IFFEAT:
case UNRES_TYPE_DFLT:
case UNRES_CHOICE_DFLT:
case UNRES_LIST_KEYS:
diff --git a/src/resolve.h b/src/resolve.h
index 37a0fb6..ea920f3 100644
--- a/src/resolve.h
+++ b/src/resolve.h
@@ -97,6 +97,16 @@
int parse_schema_json_predicate(const char *id, const char **name, int *nam_len, const char **value, int *val_len,
int *has_predicate);
+/**
+ * @param[in] expr compiled if-feature expression
+ * @return 0 if enabled, 1 if disabled
+ */
+int resolve_iffeature(struct lys_iffeature *expr);
+void resolve_iffeature_getsizes(struct lys_iffeature *iffeat, unsigned int *expr_size, unsigned int *feat_size);
+int resolve_iffeature_compile(struct lys_iffeature *iffeat_expr, const char *value, struct lys_node *node,
+ struct unres_schema *unres);
+uint8_t iff_getop(uint8_t *list, int pos);
+
struct lyd_node *resolve_data_descendant_schema_nodeid(const char *nodeid, struct lyd_node *start);
int resolve_augment_schema_nodeid(const char *nodeid, const struct lys_node *start, const struct lys_module *module,
diff --git a/src/tree_data.c b/src/tree_data.c
index fe6f7fa..511e8cf 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -52,7 +52,7 @@
assert(ctx);
- if (data && lys_parent(data->schema)) {
+ if (data && lys_parent(data->schema) && (data->schema->nodetype != LYS_ACTION)) {
LOGERR(LY_EINVAL, "Subtree are not top-level data.");
return EXIT_FAILURE;
}
@@ -83,13 +83,18 @@
return EXIT_FAILURE;
}
} else if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY)) {
- if (!data || data->parent || (data->prev != data) || (data->schema->nodetype != LYS_RPC)) {
- LOGERR(LY_EINVAL, "Subtree is not a single RPC.");
+ if (!data || data->parent || (data->prev != data) || !(data->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
+ LOGERR(LY_EINVAL, "Subtree is not a single RPC/reply.");
return EXIT_FAILURE;
}
if (ly_check_mandatory(data, NULL, 1, (options & LYD_OPT_RPCREPLY) ? 1 : 0)) {
return EXIT_FAILURE;
}
+ } else if (options & LYD_OPT_ACTION) {
+ if (!data || data->parent || (data->prev != data) || !(data->schema->nodetype & (LYS_CONTAINER | LYS_LIST))) {
+ LOGERR(LY_EINVAL, "Subtree is not a single action.");
+ return EXIT_FAILURE;
+ }
} else {
LOGINT;
return EXIT_FAILURE;
@@ -142,7 +147,7 @@
static struct lyd_node *
lyd_parse_data_(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options, va_list ap)
{
- const struct lys_node *rpc = NULL;
+ const struct lys_node *rpc_act = NULL;
if (lyp_check_options(options)) {
LOGERR(LY_EINVAL, "%s: Invalid options (multiple data type flags set).", __func__);
@@ -150,14 +155,14 @@
}
if (options & LYD_OPT_RPCREPLY) {
- rpc = va_arg(ap, struct lys_node*);
- if (!rpc || (rpc->nodetype != LYS_RPC)) {
+ rpc_act = va_arg(ap, struct lys_node *);
+ if (!rpc_act || !(rpc_act->nodetype & (LYS_RPC | LYS_ACTION))) {
LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
return NULL;
}
}
- return lyd_parse_(ctx, rpc, data, format, options);
+ return lyd_parse_(ctx, rpc_act, data, format, options);
}
API struct lyd_node *
@@ -271,7 +276,7 @@
return siblings;
}
-static struct lyd_node *
+struct lyd_node *
_lyd_new(struct lyd_node *parent, const struct lys_node *schema)
{
struct lyd_node *ret;
@@ -313,7 +318,7 @@
return NULL;
}
- if (lys_get_data_sibling(module, siblings, name, LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC, &snode)
+ if (lys_get_data_sibling(module, siblings, name, LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC | LYS_ACTION, &snode)
|| !snode) {
ly_errno = LY_EINVAL;
return NULL;
@@ -582,7 +587,7 @@
return NULL;
}
- if (lys_get_data_sibling(module, siblings, name, LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC, &snode)
+ if (lys_get_data_sibling(module, siblings, name, LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC | LYS_ACTION, &snode)
|| !snode) {
return NULL;
}
@@ -834,7 +839,7 @@
/* find the schema node */
schild = NULL;
while ((schild = lys_getnext(schild, sparent, module, 0))) {
- if (schild->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYXML | LYS_NOTIF | LYS_RPC)) {
+ if (schild->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYXML | LYS_NOTIF | LYS_RPC | LYS_ACTION)) {
/* module comparison */
if (mod_name) {
node_mod_name = lys_node_module(schild)->name;
@@ -881,6 +886,7 @@
case LYS_LIST:
case LYS_NOTIF:
case LYS_RPC:
+ case LYS_ACTION:
node = _lyd_new(is_relative ? parent : NULL, schild);
break;
case LYS_LEAF:
@@ -2267,13 +2273,13 @@
/* check placing the node to the appropriate place according to the schema */
for (sparent = lys_parent(node->schema);
- sparent && !(sparent->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_NOTIF));
+ sparent && !(sparent->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_ACTION | LYS_NOTIF));
sparent = lys_parent(sparent));
if (sparent != parent->schema) {
return EXIT_FAILURE;
}
- if (node->parent != parent || (invalid = lyp_is_rpc(node->schema))) {
+ if (node->parent != parent || (invalid = lyp_is_rpc_action(node->schema))) {
/* it is not just moving under a parent node or it is in an RPC where
* nodes order matters, so the validation will be necessary */
invalid++;
@@ -2322,17 +2328,17 @@
/* check placing the node to the appropriate place according to the schema */
for (par1 = lys_parent(sibling->schema);
- par1 && !(par1->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF));
+ par1 && !(par1->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_INPUT | LYS_OUTPUT | LYS_ACTION | LYS_NOTIF));
par1 = lys_parent(par1));
for (par2 = lys_parent(node->schema);
- par2 && !(par2->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF));
+ par2 && !(par2->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_INPUT | LYS_OUTPUT | LYS_ACTION | LYS_NOTIF));
par2 = lys_parent(par2));
if (par1 != par2) {
ly_errno = LY_EINVAL;
return EXIT_FAILURE;
}
- if (node->parent != sibling->parent || (invalid = lyp_is_rpc(node->schema)) || !node->parent) {
+ if (node->parent != sibling->parent || (invalid = lyp_is_rpc_action(node->schema)) || !node->parent) {
/* a) it is not just moving under a parent node (invalid = 1) or
* b) it is in an RPC where nodes order matters (invalid = 2) or
* c) it is top-level where we don't know if it is the same tree (invalid = 1),
@@ -2597,7 +2603,7 @@
/* sort all the children recursively */
if (recursive) {
LY_TREE_FOR(sibling, node) {
- if ((node->schema->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_NOTIF))
+ if ((node->schema->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_ACTION | LYS_NOTIF))
&& lyd_schema_sort(node->child, recursive)) {
return -1;
}
@@ -2626,7 +2632,7 @@
API int
lyd_validate(struct lyd_node **node, int options, ...)
{
- struct lyd_node *root, *next1, *next2, *iter, *to_free = NULL;
+ struct lyd_node *root, *next1, *next2, *iter, *action = NULL, *to_free = NULL;
struct ly_ctx *ctx = NULL;
int ret = EXIT_FAILURE, ap_flag = 0;
va_list ap;
@@ -2670,6 +2676,11 @@
}
}
+ if ((options & LYD_OPT_RPC) && *node && ((*node)->schema->nodetype != LYS_RPC)) {
+ options &= ~LYD_OPT_RPC;
+ options |= LYD_OPT_ACTION;
+ }
+
if (lyd_check_topmandatory(*node, ctx, options)) {
goto error;
}
@@ -2681,6 +2692,12 @@
to_free = NULL;
}
+ if ((options & LYD_OPT_ACTION) && (iter->schema->nodetype == LYS_ACTION)) {
+ options &= ~LYD_OPT_ACTION;
+ options |= LYD_OPT_RPC;
+ action = iter;
+ }
+
if (lyv_data_context(iter, options, unres)) {
goto error;
}
@@ -2756,7 +2773,12 @@
}
/* add default values if needed */
- if (lyd_defaults_add_unres(node, options, ctx, unres)) {
+ if (action) {
+ /* it will not get deleted */
+ if (lyd_defaults_add_unres(&action, options, ctx, unres)) {
+ goto error;
+ }
+ } else if (lyd_defaults_add_unres(node, options, ctx, unres)) {
goto error;
}
@@ -2974,6 +2996,7 @@
case LYS_LIST:
case LYS_NOTIF:
case LYS_RPC:
+ case LYS_ACTION:
new_node = malloc(sizeof *new_node);
if (!new_node) {
LOGMEM;
@@ -3623,7 +3646,7 @@
unsigned int i, j;
if (!data || !schema ||
- !(schema->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_ANYXML | LYS_NOTIF | LYS_RPC))) {
+ !(schema->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_ANYXML | LYS_NOTIF | LYS_RPC | LYS_ACTION))) {
ly_errno = LY_EINVAL;
return NULL;
}
@@ -3650,7 +3673,7 @@
if (siter->nodetype == LYS_AUGMENT) {
siter = ((struct lys_node_augment *)siter)->target;
continue;
- } else if (siter->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_ANYXML | LYS_NOTIF | LYS_RPC)) {
+ } else if (siter->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_ANYXML | LYS_NOTIF | LYS_RPC | LYS_RPC)) {
/* standard data node */
ly_set_add(spath, (void*)siter, LY_SET_OPT_USEASLIST);
@@ -4329,12 +4352,12 @@
break;
case LYS_INPUT:
case LYS_OUTPUT:
- assert(options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY));
+ assert(options & (LYD_OPT_RPC | LYD_OPT_ACTION | LYD_OPT_RPCREPLY));
if ((siter->nodetype == LYS_INPUT) && (options & LYD_OPT_RPCREPLY)) {
/* skip input */
break;
}
- if ((siter->nodetype == LYS_OUTPUT) && (options & LYD_OPT_RPC)) {
+ if ((siter->nodetype == LYS_OUTPUT) && (options & (LYD_OPT_RPC | LYD_OPT_ACTION))) {
/* skip output */
break;
}
@@ -4406,7 +4429,7 @@
}
}
- if (iter->schema->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_NOTIF)) {
+ if (iter->schema->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
if ((options & LYD_WD_MASK) == LYD_WD_EXPLICIT
&& ((iter->schema->flags & LYS_CONFIG_W) && !(iter->schema->flags & LYS_INCL_STATUS))) {
/* do not process config data in explicit mode */
@@ -4582,18 +4605,14 @@
LOGERR(LY_EINVAL, "Cannot add default values to RPC, RPC reply, and notification without at least the empty container.");
return EXIT_FAILURE;
}
- if ((options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY)) && ((*root)->schema->nodetype != LYS_RPC)) {
- LOGERR(LY_EINVAL, "Not valid RPC data.");
+ if ((options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY)) && !((*root)->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
+ LOGERR(LY_EINVAL, "Not valid RPC/action data.");
return EXIT_FAILURE;
}
if ((options & LYD_OPT_NOTIF) && ((*root)->schema->nodetype != LYS_NOTIF)) {
LOGERR(LY_EINVAL, "Not valid notification data.");
return EXIT_FAILURE;
}
- if (!(options & LYD_OPT_NOSIBLINGS) && ((*root)->prev != (*root))) {
- LOGERR(LY_EINVAL, "Additional invalid data with an RPC, RPC reply, or notification.");
- return EXIT_FAILURE;
- }
} else if (*root && (*root)->parent) {
/* we have inner node, so it will be considered as
* a root of subtree where to add default nodes and
diff --git a/src/tree_data.h b/src/tree_data.h
index 8a405b1..854ead6 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -381,7 +381,7 @@
#define LYD_OPT_RPC 0x10 /**< Data represents RPC's input parameters. */
#define LYD_OPT_RPCREPLY 0x20 /**< Data represents RPC's output parameters (maps to NETCONF <rpc-reply> data). */
#define LYD_OPT_NOTIF 0x40 /**< Data represents an event notification data. */
-/* 0x80 reserved, formerly LYD_OPT_FILTER */
+/* 0x80 reserved, formerly LYD_OPT_FILTER, now used internally */
#define LYD_OPT_TYPEMASK 0xff /**< Mask to filter data type options. Always only a single data type option (only
single bit from the lower 8 bits) can be set. */
diff --git a/src/tree_internal.h b/src/tree_internal.h
index 6a5b928..c1f1699 100644
--- a/src/tree_internal.h
+++ b/src/tree_internal.h
@@ -59,6 +59,11 @@
#define LY_NSNACM "urn:ietf:params:xml:ns:yang:ietf-netconf-acm"
/**
+ * @brief internal parser flag for actions
+ */
+#define LYD_OPT_ACTION 0x80
+
+/**
* @brief Internal list of built-in types
*/
struct ly_types {
@@ -286,6 +291,15 @@
int ly_check_mandatory(const struct lyd_node *data, const struct lys_node *schema, int status, int rpc_output);
/**
+ * @brief Create a data container knowing it's schema node.
+ *
+ * @param[in] parent Data parent of the new node.
+ * @param[in] schema Schema node of the new node.
+ * @return New node, NULL on error.
+ */
+struct lyd_node *_lyd_new(struct lyd_node *parent, const struct lys_node *schema);
+
+/**
* @brief Find the parent node of an attribute.
*
* @param[in] root Root element of the data tree with the attribute.
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 1b96cd0..3fa333d 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -40,7 +40,7 @@
lys_type_dup(struct lys_module *mod, struct lys_node *parent, struct lys_type *new, struct lys_type *old,
struct unres_schema *unres);
-API const struct lys_feature *
+API const struct lys_node *
lys_is_disabled(const struct lys_node *node, int recursive)
{
int i;
@@ -50,9 +50,9 @@
/* input/output does not have if-feature, so skip them */
/* check local if-features */
- for (i = 0; i < node->features_size; i++) {
- if (!(node->features[i]->flags & LYS_FENABLED)) {
- return node->features[i];
+ for (i = 0; i < node->iffeature_size; i++) {
+ if (resolve_iffeature(&node->iffeature[i])) {
+ return node;
}
}
}
@@ -234,6 +234,7 @@
goto repeat;
case LYS_RPC:
+ case LYS_ACTION:
case LYS_NOTIF:
case LYS_CONTAINER:
case LYS_LEAF:
@@ -944,6 +945,13 @@
case LYS_CONTAINER:
case LYS_LIST:
case LYS_GROUPING:
+ if (!(child->nodetype &
+ (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
+ LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION))) {
+ LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
+ return EXIT_FAILURE;
+ }
+ break;
case LYS_USES:
case LYS_INPUT:
case LYS_OUTPUT:
@@ -954,7 +962,6 @@
LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
return EXIT_FAILURE;
}
-
break;
case LYS_CHOICE:
if (!(child->nodetype &
@@ -971,6 +978,7 @@
}
break;
case LYS_RPC:
+ case LYS_ACTION:
if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
return EXIT_FAILURE;
@@ -986,7 +994,7 @@
case LYS_AUGMENT:
if (!(child->nodetype &
(LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
- | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
+ | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ACTION))) {
LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
return EXIT_FAILURE;
}
@@ -1638,6 +1646,18 @@
}
static void
+lys_iffeature_free(struct lys_iffeature *iffeature, uint8_t iffeature_size)
+{
+ uint8_t i;
+
+ for (i = 0; i < iffeature_size; ++i) {
+ free(iffeature[i].expr);
+ free(iffeature[i].features);
+ }
+ free(iffeature);
+}
+
+static void
lys_augment_free(struct ly_ctx *ctx, struct lys_node_augment *aug, void (*private_destructor)(const struct lys_node *node, void *priv))
{
struct lys_node *next, *sub;
@@ -1653,7 +1673,7 @@
lydict_remove(ctx, aug->dsc);
lydict_remove(ctx, aug->ref);
- free(aug->features);
+ lys_iffeature_free(aug->iffeature, aug->iffeature_size);
lys_when_free(ctx, aug->when);
}
@@ -1788,7 +1808,7 @@
}
static void
-lys_rpc_inout_free(struct ly_ctx *ctx, struct lys_node_rpc_inout *io)
+lys_inout_free(struct ly_ctx *ctx, struct lys_node_inout *io)
{
int i;
@@ -1911,7 +1931,7 @@
lydict_remove(ctx, f->name);
lydict_remove(ctx, f->dsc);
lydict_remove(ctx, f->ref);
- free(f->features);
+ lys_iffeature_free(f->iffeature, f->iffeature_size);
}
static void
@@ -2018,7 +2038,7 @@
/* common part */
lydict_remove(ctx, node->name);
if (!(node->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
- free(node->features);
+ lys_iffeature_free(node->iffeature, node->iffeature_size);
lydict_remove(ctx, node->dsc);
lydict_remove(ctx, node->ref);
}
@@ -2060,13 +2080,14 @@
break;
case LYS_GROUPING:
case LYS_RPC:
+ case LYS_ACTION:
case LYS_NOTIF:
lys_grp_free(ctx, (struct lys_node_grp *)node);
break;
case LYS_INPUT:
case LYS_OUTPUT:
- lys_rpc_inout_free(ctx, (struct lys_node_rpc_inout *)node);
+ lys_inout_free(ctx, (struct lys_node_inout *)node);
break;
case LYS_UNKNOWN:
LOGINT;
@@ -2217,6 +2238,7 @@
struct lys_node *retval = NULL, *child;
struct ly_ctx *ctx = module->ctx;
int i, j, rc;
+ unsigned int size, size1, size2;
struct lys_node_container *cont = NULL;
struct lys_node_container *cont_orig = (struct lys_node_container *)node;
@@ -2234,12 +2256,12 @@
struct lys_node_uses *uses_orig = (struct lys_node_uses *)node;
struct lys_node_grp *grp = NULL;
struct lys_node_grp *grp_orig = (struct lys_node_grp *)node;
- struct lys_node_rpc *rpc = NULL;
- struct lys_node_rpc *rpc_orig = (struct lys_node_rpc *)node;
- struct lys_node_rpc_inout *io = NULL;
- struct lys_node_rpc_inout *io_orig = (struct lys_node_rpc_inout *)node;
- struct lys_node_rpc *ntf = NULL;
- struct lys_node_rpc *ntf_orig = (struct lys_node_rpc *)node;
+ struct lys_node_rpc_action *rpc = NULL;
+ struct lys_node_rpc_action *rpc_orig = (struct lys_node_rpc_action *)node;
+ struct lys_node_inout *io = NULL;
+ struct lys_node_inout *io_orig = (struct lys_node_inout *)node;
+ struct lys_node_rpc_action *ntf = NULL;
+ struct lys_node_rpc_action *ntf_orig = (struct lys_node_rpc_action *)node;
struct lys_node_case *cs = NULL;
struct lys_node_case *cs_orig = (struct lys_node_case *)node;
@@ -2294,6 +2316,7 @@
break;
case LYS_RPC:
+ case LYS_ACTION:
rpc = calloc(1, sizeof *rpc);
retval = (struct lys_node *)rpc;
break;
@@ -2337,18 +2360,44 @@
retval->prev = retval;
- retval->features_size = node->features_size;
- retval->features = calloc(retval->features_size, sizeof *retval->features);
- if (!retval->features) {
+ retval->iffeature_size = node->iffeature_size;
+ retval->iffeature = calloc(retval->iffeature_size, sizeof *retval->iffeature);
+ if (!retval->iffeature) {
LOGMEM;
goto error;
}
if (!shallow) {
- for (i = 0; i < node->features_size; ++i) {
- retval->features[i] = (struct lys_feature *)retval;
- if (unres_schema_dup(module, unres, &node->features[i], UNRES_IFFEAT, &retval->features[i])) {
- retval->features[i] = node->features[i];
+ for (i = 0; i < node->iffeature_size; ++i) {
+ resolve_iffeature_getsizes(&node->iffeature[i], &size1, &size2);
+ if (size1) {
+ /* there is something to duplicate */
+
+ /* duplicate compiled expression */
+ size = (size1 / 4) + (size1 % 4) ? 1 : 0;
+ retval->iffeature[i].expr = malloc(size * sizeof *retval->iffeature[i].expr);
+ memcpy(retval->iffeature[i].expr, node->iffeature[i].expr, size * sizeof *retval->iffeature[i].expr);
+
+ /* list of feature pointer must be updated to point to the resulting tree */
+ retval->iffeature[i].features = malloc(size2 * sizeof *retval->iffeature[i].features);
+ for (j = 0; (unsigned int)j < size2; j++) {
+ rc = unres_schema_dup(module, unres, &node->iffeature[i].features[j], UNRES_IFFEAT,
+ &retval->iffeature[i].features[j]);
+ if (rc == EXIT_SUCCESS) {
+ /* feature is not resolved, duplicate the expression string */
+ retval->iffeature[i].features[j] = (void *)strdup((char *)node->iffeature[i].features[j]);
+ } else if (rc == EXIT_FAILURE) {
+ /* feature is resolved in origin, so copy it
+ * - duplication is used for instantiating groupings
+ * and if-feature inside grouping is supposed to be
+ * resolved inside the original grouping, so we want
+ * to keep pointers to features from the grouping
+ * context */
+ retval->iffeature[i].features[j] = node->iffeature[i].features[j];
+ } else if (rc == -1) {
+ goto error;
+ }
+ }
}
}
@@ -2366,7 +2415,7 @@
}
}
} else {
- memcpy(retval->features, node->features, retval->features_size * sizeof *retval->features);
+ memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature);
}
/*
@@ -2703,12 +2752,16 @@
for (i = 0; i < module->features_size; i++) {
if (all || !strcmp(module->features[i].name, name)) {
if (op) {
- module->features[i].flags |= LYS_FENABLED;
- /* enable referenced features (recursion) */
- for (k = 0; k < module->features[i].features_size; k++) {
- lys_features_change(module->features[i].features[k]->module,
- module->features[i].features[k]->name, op);
+ /* check referenced features if they are enabled */
+ for (j = 0; j < module->features[i].iffeature_size; j++) {
+ if (resolve_iffeature(&module->features[i].iffeature[j])) {
+ LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
+ module->features[i].name, j + 1);
+ return EXIT_FAILURE;
+ }
}
+
+ module->features[i].flags |= LYS_FENABLED;
} else {
module->features[i].flags &= ~LYS_FENABLED;
}
@@ -2719,13 +2772,22 @@
}
/* submodules */
- for (j = 0; j < module->inc_size; j++) {
- for (i = 0; i < module->inc[j].submodule->features_size; i++) {
- if (all || !strcmp(module->inc[j].submodule->features[i].name, name)) {
+ for (i = 0; i < module->inc_size; i++) {
+ for (j = 0; j < module->inc[i].submodule->features_size; j++) {
+ if (all || !strcmp(module->inc[i].submodule->features[j].name, name)) {
if (op) {
- module->inc[j].submodule->features[i].flags |= LYS_FENABLED;
+ /* check referenced features if they are enabled */
+ for (k = 0; k < module->inc[i].submodule->features[j].iffeature_size; k++) {
+ if (resolve_iffeature(&module->inc[i].submodule->features[j].iffeature[k])) {
+ LOGERR(LY_EINVAL, "Feature \"%s\" is disabled by its %d. if-feature condition.",
+ module->inc[i].submodule->features[j].name, k + 1);
+ return EXIT_FAILURE;
+ }
+ }
+
+ module->inc[i].submodule->features[j].flags |= LYS_FENABLED;
} else {
- module->inc[j].submodule->features[i].flags &= ~LYS_FENABLED;
+ module->inc[i].submodule->features[j].flags &= ~LYS_FENABLED;
}
if (!all) {
return EXIT_SUCCESS;
@@ -2902,7 +2964,7 @@
{
struct lys_node_leaf *iter = leafref_target;
- if (leafref_target->nodetype != LYS_LEAF) {
+ if (!(leafref_target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
LOGINT;
return -1;
}
@@ -2918,7 +2980,7 @@
}
/* create fake child - the ly_set structure to hold the list of
- * leafrefs referencing the leaf */
+ * leafrefs referencing the leaf(-list) */
if (!leafref_target->child) {
leafref_target->child = (void*)ly_set_new();
if (!leafref_target->child) {
diff --git a/src/tree_schema.h b/src/tree_schema.h
index a929920..f13d450 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -204,13 +204,14 @@
LYS_OUTPUT = 0x0400, /**< output statement node */
LYS_GROUPING = 0x0800, /**< grouping statement node */
LYS_USES = 0x1000, /**< uses statement node */
- LYS_AUGMENT = 0x2000 /**< augment statement node */
+ LYS_AUGMENT = 0x2000, /**< augment statement node */
+ LYS_ACTION = 0x4000 /**< action statement node */
} LYS_NODE;
/* all nodes sharing the node namespace except RPCs and notifications */
#define LYS_NO_RPC_NOTIF_NODE 0x007F
-#define LYS_ANY 0x3FFF
+#define LYS_ANY 0x7FFF
/**
* @brief Main schema node structure representing YANG module.
@@ -234,7 +235,7 @@
uint8_t version:5; /**< yang-version:
- 0 = not specified, YANG 1.0 as default,
- 1 = YANG 1.0,
- - 2 = YANG 1.1 not yet supported */
+ - 2 = YANG 1.1 */
uint8_t deviated:1; /**< deviated flag (true/false) if the module is deviated by some other module */
uint8_t implemented:1; /**< flag if the module is implemented, not just imported */
@@ -540,6 +541,19 @@
*/
};
+#define LYS_IFF_NOT 0x00
+#define LYS_IFF_AND 0x01
+#define LYS_IFF_OR 0x02
+#define LYS_IFF_F 0x03
+
+/**
+ * @brief Compiled if-feature expression structure
+ */
+struct lys_iffeature {
+ uint8_t *expr; /**< 2bits array describing the if-feature expression in prefix format */
+ struct lys_feature **features; /**< array of pointers to the features used in expression */
+};
+
/**
* @defgroup nacmflags NACM flags
* @ingroup schematree
@@ -657,9 +671,8 @@
itself. In case of the first node, this pointer points to the last
node in the list. */
- uint8_t features_size; /**< number of elements in the #features array */
- struct lys_feature **features; /**< array of pointers to feature definitions, this is not the array of feature
- definitions themselves, but the array of if-feature references */
+ uint8_t iffeature_size; /**< number of elements in the #iffeature array */
+ struct lys_iffeature *iffeature; /**< array of if-feature expressions */
void *priv; /**< private caller's data, not used by libyang */
};
@@ -689,9 +702,8 @@
itself. In case of the first node, this pointer points to the last
node in the list. */
- uint8_t features_size; /**< number of elements in the #features array */
- struct lys_feature **features; /**< array of pointers to feature definitions, this is not the array of feature
- definitions themselves, but the array of if-feature references */
+ uint8_t iffeature_size; /**< number of elements in the #iffeature array */
+ struct lys_iffeature *iffeature; /**< array of if-feature expressions */
void *priv; /**< private caller's data, not used by libyang */
/* specific container's data */
@@ -731,9 +743,8 @@
itself. In case of the first node, this pointer points to the last
node in the list. */
- uint8_t features_size; /**< number of elements in the #features array */
- struct lys_feature **features; /**< array of pointers to feature definitions, this is not the array of feature
- definitions themselves, but the array of if-feature references */
+ uint8_t iffeature_size; /**< number of elements in the #iffeature array */
+ struct lys_iffeature *iffeature; /**< array of if-feature expressions */
void *priv; /**< private caller's data, not used by libyang */
/* specific choice's data */
@@ -773,9 +784,8 @@
itself. In case of the first node, this pointer points to the last
node in the list. */
- uint8_t features_size; /**< number of elements in the #features array */
- struct lys_feature **features; /**< array of pointers to feature definitions, this is not the array of feature
- definitions themselves, but the array of if-feature references */
+ uint8_t iffeature_size; /**< number of elements in the #iffeature array */
+ struct lys_iffeature *iffeature; /**< array of if-feature expressions */
void *priv; /**< private caller's data, not used by libyang */
/* specific leaf's data */
@@ -821,9 +831,8 @@
itself. In case of the first node, this pointer points to the last
node in the list. */
- uint8_t features_size; /**< number of elements in the #features array */
- struct lys_feature **features; /**< array of pointers to feature definitions, this is not the array of feature
- definitions themselves, but the array of if-feature references */
+ uint8_t iffeature_size; /**< number of elements in the #iffeature array */
+ struct lys_iffeature *iffeature; /**< array of if-feature expressions */
void *priv; /**< private caller's data, not used by libyang */
/* specific leaf-list's data */
@@ -865,9 +874,8 @@
itself. In case of the first node, this pointer points to the last
node in the list. */
- uint8_t features_size; /**< number of elements in the #features array */
- struct lys_feature **features; /**< array of pointers to feature definitions, this is not the array of feature
- definitions themselves, but the array of if-feature references */
+ uint8_t iffeature_size; /**< number of elements in the #iffeature array */
+ struct lys_iffeature *iffeature; /**< array of if-feature expressions */
void *priv; /**< private caller's data, not used by libyang */
/* specific list's data */
@@ -915,9 +923,8 @@
itself. In case of the first node, this pointer points to the last
node in the list. */
- uint8_t features_size; /**< number of elements in the #features array */
- struct lys_feature **features; /**< array of pointers to feature definitions, this is not the array of feature
- definitions themselves, but the array of if-feature references */
+ uint8_t iffeature_size; /**< number of elements in the #iffeature array */
+ struct lys_iffeature *iffeature; /**< array of if-feature expressions */
void *priv; /**< private caller's data, not used by libyang */
/* specific anyxml's data */
@@ -956,9 +963,8 @@
itself. In case of the first node, this pointer points to the last
node in the list. */
- uint8_t features_size; /**< number of elements in the #features array */
- struct lys_feature **features; /**< array of pointers to feature definitions, this is not the array of feature
- definitions themselves, but the array of if-feature references */
+ uint8_t iffeature_size; /**< number of elements in the #iffeature array */
+ struct lys_iffeature *iffeature; /**< array of if-feature expressions */
void *priv; /**< private caller's data, not used by libyang */
/* specific uses's data */
@@ -1004,9 +1010,8 @@
itself. In case of the first node, this pointer points to the last
node in the list. */
- uint8_t features_size; /**< number of elements in the #features array */
- struct lys_feature **features; /**< array of pointers to feature definitions, this is not the array of feature
- definitions themselves, but the array of if-feature references */
+ uint8_t iffeature_size; /**< number of elements in the #iffeature array */
+ struct lys_iffeature *iffeature; /**< array of if-feature expressions */
void *priv; /**< private caller's data, not used by libyang */
/* specific grouping's data */
@@ -1039,9 +1044,8 @@
itself. In case of the first node, this pointer points to the last
node in the list. */
- uint8_t features_size; /**< number of elements in the #features array */
- struct lys_feature **features; /**< array of pointers to feature definitions, this is not the array of feature
- definitions themselves, but the array of if-feature references */
+ uint8_t iffeature_size; /**< number of elements in the #iffeature array */
+ struct lys_iffeature *iffeature; /**< array of if-feature expressions */
void *priv; /**< private caller's data, not used by libyang */
/* specific case's data */
@@ -1059,7 +1063,7 @@
* member.
*
*/
-struct lys_node_rpc_inout {
+struct lys_node_inout {
const char *name;
void *fill1[2]; /**< padding for compatibility with ::lys_node - dsc and ref */
uint16_t fill2[1]; /**< padding for compatibility with ::lys_node - flags and nacm */
@@ -1105,9 +1109,8 @@
itself. In case of the first node, this pointer points to the last
node in the list. */
- uint8_t features_size; /**< number of elements in the #features array */
- struct lys_feature **features; /**< array of pointers to feature definitions, this is not the array of feature
- definitions themselves, but the array of if-feature references */
+ uint8_t iffeature_size; /**< number of elements in the #iffeature array */
+ struct lys_iffeature *iffeature; /**< array of if-feature expressions */
void *priv; /**< private caller's data, not used by libyang */
/* specific rpc's data */
@@ -1121,7 +1124,7 @@
* Beginning of the structure is completely compatible with ::lys_node structure extending it by the #tpdf_size and
* #tpdf members.
*/
-struct lys_node_rpc {
+struct lys_node_rpc_action {
const char *name; /**< node name (mandatory) */
const char *dsc; /**< description statement (optional) */
const char *ref; /**< reference statement (optional) */
@@ -1129,7 +1132,7 @@
uint16_t nacm:2; /**< [NACM extension flags](@ref nacmflags) */
struct lys_module *module; /**< pointer to the node's module (mandatory) */
- LYS_NODE nodetype; /**< type of the node (mandatory) - #LYS_RPC */
+ LYS_NODE nodetype; /**< type of the node (mandatory) - #LYS_RPC or #LYS_ACTION */
struct lys_node *parent; /**< pointer to the parent node, NULL in case of a top level node */
struct lys_node *child; /**< pointer to the first child node */
struct lys_node *next; /**< pointer to the next sibling node (NULL if there is no one) */
@@ -1138,9 +1141,8 @@
itself. In case of the first node, this pointer points to the last
node in the list. */
- uint8_t features_size; /**< number of elements in the #features array */
- struct lys_feature **features; /**< array of pointers to feature definitions, this is not the array of feature
- definitions themselves, but the array of if-feature references */
+ uint8_t iffeature_size; /**< number of elements in the #iffeature array */
+ struct lys_iffeature *iffeature; /**< array of if-feature expressions */
void *priv; /**< private caller's data, not used by libyang */
/* specific rpc's data */
@@ -1183,9 +1185,8 @@
struct lys_node *target; /**< pointer to the target node */
/* again compatible members with ::lys_node */
- uint8_t features_size; /**< number of elements in the #features array */
- struct lys_feature **features; /**< array of pointers to feature definitions, this is not the array of feature
- definitions themselves, but the array of if-feature references */
+ uint8_t iffeature_size; /**< number of elements in the #iffeature array */
+ struct lys_iffeature *iffeature; /**< array of if-feature expressions */
void *priv; /**< private caller's data, not used by libyang */
};
@@ -1338,9 +1339,8 @@
uint16_t padding:2;
struct lys_module *module; /**< link to the features's data model (mandatory) */
- uint8_t features_size; /**< number of elements in the #features array */
- struct lys_feature **features; /**< array of pointers to feature definitions, this is not the array of feature
- definitions themselves, but the array of if-feature references */
+ uint8_t iffeature_size; /**< number of elements in the #iffeature array */
+ struct lys_iffeature *iffeature; /**< array of if-feature expressions */
};
/**
@@ -1477,9 +1477,9 @@
* - 1 to check if-feature in all ascendant schema nodes
* - 2 to check if-feature in all ascendant schema nodes until there a node having an instance in a data tree
* @return - NULL if enabled,
- * - pointer to the disabling feature if disabled.
+ * - pointer to the node with the unsatisfied (disabling) if-feature expression.
*/
-const struct lys_feature *lys_is_disabled(const struct lys_node *node, int recursive);
+const struct lys_node *lys_is_disabled(const struct lys_node *node, int recursive);
/**
* @brief Get next schema tree (sibling) node element that can be instantiated in a data tree. Returned node can
diff --git a/src/validation.c b/src/validation.c
index bd227b9..9a3e93f 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -25,7 +25,7 @@
#include "tree_internal.h"
#include "xml_internal.h"
-static int
+int
lyv_keys(const struct lyd_node *list)
{
struct lyd_node *child;
@@ -95,7 +95,7 @@
}
/* check elements order in case of RPC's input and output */
- if (node->validity && lyp_is_rpc(node->schema)) {
+ if (node->validity && lyp_is_rpc_action(node->schema)) {
if ((node->prev != node) && node->prev->next) {
for (siter = lys_getnext(node->schema, lys_parent(node->schema), node->schema->module, 0);
siter;
@@ -138,7 +138,7 @@
/* mandatory children */
if ((schema->nodetype & (LYS_CONTAINER | LYS_LIST))
- && !(options & (LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
+ && !(options & (LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG | LYD_OPT_ACTION))) {
if (ly_check_mandatory(node, NULL, (options & LYD_OPT_TYPEMASK) ? 0 : 1, (options & LYD_OPT_RPCREPLY) ? 1 : 0)) {
return EXIT_FAILURE;
}
diff --git a/src/yang.y.in b/src/yang.y.in
index 2d96a9e..a06a4b9 100644
--- a/src/yang.y.in
+++ b/src/yang.y.in
@@ -385,12 +385,12 @@
yang_version_stmt: YANG_VERSION_KEYWORD sep yang_version_arg_str stmtend;
-yang_version_arg_str: NON_NEGATIVE_INTEGER { if (strlen(yyget_text(scanner))!=1 || yyget_text(scanner)[0]!='1') {
+yang_version_arg_str: NON_NEGATIVE_INTEGER { if (strcmp(yyget_text(scanner), "1") && strcmp(yyget_text(scanner), "1.1")) {
YYABORT;
}
} optsep
| string_1 { if (read_all) {
- if (strlen(s)!=1 || s[0]!='1') {
+ if (strcmp(s, "1") && strcmp(s, "1.1")) {
free(s);
YYABORT;
}
@@ -780,9 +780,9 @@
feature_opt_stmt: @EMPTYDIR@ { if (read_all) {
if (size_arrays->node[size_arrays->next].if_features) {
- ((struct lys_feature*)actual)->features = calloc(size_arrays->node[size_arrays->next].if_features,
- sizeof *((struct lys_feature*)actual)->features);
- if (!((struct lys_feature*)actual)->features) {
+ ((struct lys_feature*)actual)->iffeature = calloc(size_arrays->node[size_arrays->next].if_features,
+ sizeof *((struct lys_feature*)actual)->iffeature);
+ if (!((struct lys_feature*)actual)->iffeature) {
LOGMEM;
YYABORT;
}
@@ -1493,8 +1493,8 @@
$$.container = actual;
actual_type = CONTAINER_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- $$.container->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.container->features);
- if (!$$.container->features) {
+ $$.container->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.container->iffeature);
+ if (!$$.container->iffeature) {
LOGMEM;
YYABORT;
}
@@ -1615,8 +1615,8 @@
$$.node.flag = 0;
actual_type = LEAF_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- $$.node.ptr_leaf->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_leaf->features);
- if (!$$.node.ptr_leaf->features) {
+ $$.node.ptr_leaf->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_leaf->iffeature);
+ if (!$$.node.ptr_leaf->iffeature) {
LOGMEM;
YYABORT;
}
@@ -1734,8 +1734,8 @@
$$.node.flag = 0;
actual_type = LEAF_LIST_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- $$.node.ptr_leaflist->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_leaflist->features);
- if (!$$.node.ptr_leaflist->features) {
+ $$.node.ptr_leaflist->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_leaflist->iffeature);
+ if (!$$.node.ptr_leaflist->iffeature) {
LOGMEM;
YYABORT;
}
@@ -1890,8 +1890,8 @@
$$.node.flag = 0;
actual_type = LIST_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- $$.node.ptr_list->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_list->features);
- if (!$$.node.ptr_list->features) {
+ $$.node.ptr_list->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_list->iffeature);
+ if (!$$.node.ptr_list->iffeature) {
LOGMEM;
YYABORT;
}
@@ -2080,8 +2080,8 @@
$$.choice.s = NULL;
actual_type = CHOICE_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- $$.choice.ptr_choice->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.choice.ptr_choice->features);
- if (!$$.choice.ptr_choice->features) {
+ $$.choice.ptr_choice->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.choice.ptr_choice->iffeature);
+ if (!$$.choice.ptr_choice->iffeature) {
LOGMEM;
YYABORT;
}
@@ -2203,8 +2203,8 @@
$$.cs = actual;
actual_type = CASE_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- $$.cs->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.cs->features);
- if (!$$.cs->features) {
+ $$.cs->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.cs->iffeature);
+ if (!$$.cs->iffeature) {
LOGMEM;
YYABORT;
}
@@ -2271,15 +2271,15 @@
$$.anyxml = actual;
actual_type = ANYXML_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- $$.anyxml->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.anyxml->features);
- if (!$$.anyxml->features) {
+ $$.anyxml->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.anyxml->iffeature);
+ if (!$$.anyxml->iffeature) {
LOGMEM;
YYABORT;
}
}
if (size_arrays->node[size_arrays->next].must) {
$$.anyxml->must = calloc(size_arrays->node[size_arrays->next].must, sizeof *$$.anyxml->must);
- if (!$$.anyxml->features || !$$.anyxml->must) {
+ if (!$$.anyxml->iffeature || !$$.anyxml->must) {
LOGMEM;
YYABORT;
}
@@ -2366,8 +2366,8 @@
$$.uses.config_inherit = config_inherit;
actual_type = USES_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- $$.uses.ptr_uses->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.uses.ptr_uses->features);
- if (!$$.uses.ptr_uses->features) {
+ $$.uses.ptr_uses->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.uses.ptr_uses->iffeature);
+ if (!$$.uses.ptr_uses->iffeature) {
LOGMEM;
YYABORT;
}
@@ -2679,8 +2679,8 @@
$$.node.flag = 0;
actual_type = AUGMENT_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- $$.node.ptr_augment->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_augment->features);
- if (!$$.node.ptr_augment->features) {
+ $$.node.ptr_augment->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_augment->iffeature);
+ if (!$$.node.ptr_augment->iffeature) {
LOGMEM;
YYABORT;
}
@@ -2746,7 +2746,7 @@
;
rpc_stmt: RPC_KEYWORD sep identifier_arg_str { if (read_all) {
- if (!(actual = yang_read_node(trg, NULL, s, LYS_RPC, sizeof(struct lys_node_rpc)))) {
+ if (!(actual = yang_read_node(trg, NULL, s, LYS_RPC, sizeof(struct lys_node_rpc_action)))) {
YYABORT;
}
data_node = actual;
@@ -2767,8 +2767,8 @@
$$.node.flag = 0;
actual_type = RPC_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- $$.node.ptr_rpc->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_rpc->features);
- if (!$$.node.ptr_rpc->features) {
+ $$.node.ptr_rpc->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_rpc->iffeature);
+ if (!$$.node.ptr_rpc->iffeature) {
LOGMEM;
YYABORT;
}
@@ -2857,7 +2857,7 @@
LOGMEM;
YYABORT;
}
- if (!(actual = yang_read_node(trg, actual, s, LYS_INPUT, sizeof(struct lys_node_rpc_inout)))) {
+ if (!(actual = yang_read_node(trg, actual, s, LYS_INPUT, sizeof(struct lys_node_inout)))) {
YYABORT;
}
data_node = actual;
@@ -2921,7 +2921,7 @@
LOGMEM;
YYABORT;
}
- if (!(actual = yang_read_node(trg, actual, s, LYS_OUTPUT, sizeof(struct lys_node_rpc_inout)))) {
+ if (!(actual = yang_read_node(trg, actual, s, LYS_OUTPUT, sizeof(struct lys_node_inout)))) {
YYABORT;
}
data_node = actual;
@@ -2959,8 +2959,8 @@
$$.notif = actual;
actual_type = NOTIFICATION_KEYWORD;
if (size_arrays->node[size_arrays->next].if_features) {
- $$.notif->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.notif->features);
- if (!$$.notif->features) {
+ $$.notif->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.notif->iffeature);
+ if (!$$.notif->iffeature) {
LOGMEM;
YYABORT;
}
@@ -3765,7 +3765,7 @@
string_opt_part3: @EMPTYDIR@
| string_opt_part3 '+' optsep STRING optsep
-
+
unknown_statement_end: ';'
| '{' optsep unknown_statement2_opt '}'
diff --git a/tests/api/test_tree_schema.c b/tests/api/test_tree_schema.c
index a73fff8..9624e97 100644
--- a/tests/api/test_tree_schema.c
+++ b/tests/api/test_tree_schema.c
@@ -97,14 +97,14 @@
}\
container x {\
leaf bar-leaf {\
- if-feature bar;\
+ if-feature \"bar\";\
type string;\
}\
uses gg {\
- if-feature bar;\
+ if-feature \"bar\";\
}\
leaf baz {\
- if-feature foo;\
+ if-feature \"foo\";\
type string;\
}\
leaf bubba {\
@@ -112,14 +112,14 @@
}\
}\
augment \"/x\" {\
- if-feature bar;\
+ if-feature \"bar\";\
container bar-y;\
}\
rpc bar-rpc {\
- if-feature bar;\
+ if-feature \"bar\";\
}\
rpc foo-rpc {\
- if-feature foo;\
+ if-feature \"foo\";\
}\
}";
@@ -201,14 +201,14 @@
\n\
container x {\n\
leaf bar-leaf {\n\
- if-feature bar;\n\
+ if-feature \"bar\";\n\
type string;\n\
}\n\
uses gg {\n\
- if-feature bar;\n\
+ if-feature \"bar\";\n\
}\n\
leaf baz {\n\
- if-feature foo;\n\
+ if-feature \"foo\";\n\
type string;\n\
}\n\
leaf bubba {\n\
@@ -217,15 +217,15 @@
}\n\
\n\
rpc bar-rpc {\n\
- if-feature bar;\n\
+ if-feature \"bar\";\n\
}\n\
\n\
rpc foo-rpc {\n\
- if-feature foo;\n\
+ if-feature \"foo\";\n\
}\n\
\n\
augment \"/x\" {\n\
- if-feature bar;\n\
+ if-feature \"bar\";\n\
container bar-y;\n\
}\n\
}\n";
@@ -577,7 +577,7 @@
(void) state; /* unused */
LYS_INFORMAT yang_format = LYS_IN_YIN;
const struct lys_module *module;
- const struct lys_feature *feature = NULL;
+ const struct lys_node *node = NULL;
int rc;
module = lys_parse_mem(ctx, lys_module_a, yang_format);
@@ -585,20 +585,20 @@
fail();
}
- feature = lys_is_disabled(module->data->child, 2);
- if (!feature) {
+ node = lys_is_disabled(module->data->child, 2);
+ if (!node) {
fail();
}
- assert_string_equal("bar", feature->name);
+ assert_string_equal("/a:top", node->name);
rc = lys_features_enable(module, "bar");
if (rc) {
fail();
}
- feature = lys_is_disabled(module->data->child, 2);
- if (feature) {
+ node = lys_is_disabled(module->data->child, 2);
+ if (node) {
fail();
}
}
diff --git a/tests/data/files/all-act.xml b/tests/data/files/all-act.xml
new file mode 100644
index 0000000..4231c04
--- /dev/null
+++ b/tests/data/files/all-act.xml
@@ -0,0 +1,10 @@
+<action xmlns="urn:ietf:params:xml:ns:yang:1">
+ <cont1 xmlns="urn:all">
+ <list1>
+ <leaf18>key_val</leaf18>
+ <act1>
+ <leaf24>some_input</leaf24>
+ </act1>
+ </list1>
+ </cont1>
+</action>
diff --git a/tests/data/files/all-actreply.xml b/tests/data/files/all-actreply.xml
new file mode 100644
index 0000000..afd0c9b
--- /dev/null
+++ b/tests/data/files/all-actreply.xml
@@ -0,0 +1 @@
+<leaf25 xmlns="urn:all">some_output</leaf25>
diff --git a/tests/data/files/all.yang b/tests/data/files/all.yang
index 69d5e31..c811246 100644
--- a/tests/data/files/all.yang
+++ b/tests/data/files/all.yang
@@ -1,4 +1,5 @@
module all {
+ yang-version 1.1;
namespace "urn:all";
prefix all_mod;
@@ -8,7 +9,7 @@
feature feat1 {
status "obsolete";
- if-feature feat2;
+ if-feature "feat2";
}
feature feat2;
@@ -43,12 +44,12 @@
container cont1 {
leaf leaf2 {
- if-feature feat1;
+ if-feature "feat1";
status "obsolete";
type int16;
}
uses group1 {
- if-feature feat2;
+ if-feature "feat2";
refine "leaf1" {
config true;
mandatory false;
@@ -151,6 +152,18 @@
type uint32;
}
anyxml axml1;
+ action act1 {
+ input {
+ leaf leaf24 {
+ type string;
+ }
+ }
+ output {
+ leaf leaf25 {
+ type string;
+ }
+ }
+ }
}
leaf-list llist1 {
type tdef1;
diff --git a/tests/data/files/all.yin b/tests/data/files/all.yin
index 1b7c733..010188f 100644
--- a/tests/data/files/all.yin
+++ b/tests/data/files/all.yin
@@ -2,7 +2,7 @@
<module name="all"
xmlns="urn:ietf:params:xml:ns:yang:yin:1"
xmlns:all_mod="urn:all">
- <yang-version value="1"/>
+ <yang-version value="1.1"/>
<namespace uri="urn:all"/>
<prefix value="all_mod"/>
<revision date="2016-05-23"/>
@@ -150,6 +150,18 @@
<type name="uint32"/>
</leaf>
<anyxml name="axml1"/>
+ <action name="act1">
+ <input>
+ <leaf name="leaf24">
+ <type name="string"/>
+ </leaf>
+ </input>
+ <output>
+ <leaf name="leaf25">
+ <type name="string"/>
+ </leaf>
+ </output>
+ </action>
</list>
<leaf-list name="llist1">
<type name="tdef1"/>
diff --git a/tests/data/test_parse_print.c b/tests/data/test_parse_print.c
index 0f9b944..0345c9f 100644
--- a/tests/data/test_parse_print.c
+++ b/tests/data/test_parse_print.c
@@ -60,6 +60,7 @@
fprintf(stderr, "Failed to load data model \"%s\".\n", schema);
goto error;
}
+ lys_features_enable(st->mod, "feat2");
lys_features_enable(st->mod, "*");
st->mod = lys_parse_path(st->ctx, schemadev, LYS_IN_YIN);
@@ -210,6 +211,8 @@
const char *data = TESTS_DIR"/data/files/all-data.xml";
const char *rpc = TESTS_DIR"/data/files/all-rpc.xml";
const char *rpcreply = TESTS_DIR"/data/files/all-rpcreply.xml";
+ const char *act = TESTS_DIR"/data/files/all-act.xml";
+ const char *actreply = TESTS_DIR"/data/files/all-actreply.xml";
const char *notif = TESTS_DIR"/data/files/all-notif.xml";
/* data */
@@ -285,6 +288,56 @@
lyd_free(st->dt);
st->dt = NULL;
+ /* act */
+ fd = open(act, O_RDONLY);
+ fstat(fd, &s);
+ st->str1 = malloc(s.st_size + 1);
+ assert_ptr_not_equal(st->str1, NULL);
+ assert_int_equal(read(fd, st->str1, s.st_size), s.st_size);
+ st->str1[s.st_size] = '\0';
+
+ st->dt = lyd_parse_path(st->ctx, act, LYD_XML, LYD_OPT_RPC);
+ assert_ptr_not_equal(st->dt, NULL);
+ lyd_print_mem(&(st->str2), st->dt, LYD_XML, LYP_FORMAT);
+
+ assert_string_equal(st->str1, st->str2);
+
+ close(fd);
+ fd = -1;
+ free(st->str1);
+ st->str1 = NULL;
+ free(st->str2);
+ st->str2 = NULL;
+ lyd_free(st->dt);
+ st->dt = NULL;
+
+ /* actreply */
+ fd = open(actreply, O_RDONLY);
+ fstat(fd, &s);
+ st->str1 = malloc(s.st_size + 1);
+ assert_ptr_not_equal(st->str1, NULL);
+ assert_int_equal(read(fd, st->str1, s.st_size), s.st_size);
+ st->str1[s.st_size] = '\0';
+
+ rpc_schema = ly_ctx_get_node(st->ctx, NULL, "/all:cont1/list1/act1");
+ assert_ptr_not_equal(rpc_schema, NULL);
+ assert_int_equal(rpc_schema->nodetype, LYS_ACTION);
+
+ st->dt = lyd_parse_path(st->ctx, actreply, LYD_XML, LYD_OPT_RPCREPLY, rpc_schema);
+ assert_ptr_not_equal(st->dt, NULL);
+ lyd_print_mem(&(st->str2), st->dt->child, LYD_XML, LYP_FORMAT);
+
+ assert_string_equal(st->str1, st->str2);
+
+ close(fd);
+ fd = -1;
+ free(st->str1);
+ st->str1 = NULL;
+ free(st->str2);
+ st->str2 = NULL;
+ lyd_free(st->dt);
+ st->dt = NULL;
+
/* notif */
fd = open(notif, O_RDONLY);
fstat(fd, &s);
diff --git a/tests/schema/yin/files/d2_output.yang b/tests/schema/yin/files/d2_output.yang
index 4152139..f428834 100644
--- a/tests/schema/yin/files/d2_output.yang
+++ b/tests/schema/yin/files/d2_output.yang
@@ -7,7 +7,7 @@
}
feature d2_feat {
- if-feature d1_pref:d1_feat;
+ if-feature "d1_pref:d1_feat";
}
identity d2_ident {