schema CHANGE integrate statement parser with the compilation process
Does not cover all the statements - focused mainly for yang-data
extension, so it handles schema nodes processing.
diff --git a/src/plugins_exts.h b/src/plugins_exts.h
index 7491926..75ba83e 100644
--- a/src/plugins_exts.h
+++ b/src/plugins_exts.h
@@ -86,7 +86,7 @@
* TODO
* @return LY_ENOT if the extension is disabled and should be ignored.
*/
-LY_ERR lys_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext_instance *ext, struct lysc_ext_substmt *substmts);
+LY_ERR lys_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext_instance *ext_p, struct lysc_ext_instance *ext);
/**
* @brief Free the extension instance's data compiled with ::lys_compile_extension_instance().
diff --git a/src/plugins_exts_metadata.c b/src/plugins_exts_metadata.c
index 99df4f0..a099acd 100644
--- a/src/plugins_exts_metadata.c
+++ b/src/plugins_exts_metadata.c
@@ -115,7 +115,7 @@
c_ext->substmts[ANNOTATION_SUBSTMT_REF].cardinality = LY_STMT_CARD_OPT;
c_ext->substmts[ANNOTATION_SUBSTMT_REF].storage = &annotation->ref;
- LY_CHECK_RET(lys_compile_extension_instance(cctx, p_ext, c_ext->substmts));
+ LY_CHECK_RET(lys_compile_extension_instance(cctx, p_ext, c_ext));
return LY_SUCCESS;
}
diff --git a/src/schema_compile.c b/src/schema_compile.c
index 07133d7..51ea049 100644
--- a/src/schema_compile.c
+++ b/src/schema_compile.c
@@ -619,125 +619,149 @@
}
LY_ERR
-lys_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext_instance *ext, struct lysc_ext_substmt *substmts)
+lys_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext_instance *ext_p, struct lysc_ext_instance *ext)
{
LY_ERR ret = LY_EVALID, r;
LY_ARRAY_COUNT_TYPE u;
struct lysp_stmt *stmt;
- struct lysp_qname *iffeatures, *iffeat;
void *parsed = NULL, **compiled = NULL;
- ly_bool enabled;
/* check for invalid substatements */
- for (stmt = ext->child; stmt; stmt = stmt->next) {
+ for (stmt = ext_p->child; stmt; stmt = stmt->next) {
if (stmt->flags & (LYS_YIN_ATTR | LYS_YIN_ARGUMENT)) {
continue;
}
- LY_ARRAY_FOR(substmts, u) {
- if (substmts[u].stmt == stmt->kw) {
+ LY_ARRAY_FOR(ext->substmts, u) {
+ if (ext->substmts[u].stmt == stmt->kw) {
break;
}
}
- if (u == LY_ARRAY_COUNT(substmts)) {
+ if (u == LY_ARRAY_COUNT(ext->substmts)) {
LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\" as a child of \"%s%s%s\" extension instance.",
- stmt->stmt, ext->name, ext->argument ? " " : "", ext->argument ? ext->argument : "");
+ stmt->stmt, ext_p->name, ext_p->argument ? " " : "", ext_p->argument ? ext_p->argument : "");
goto cleanup;
}
}
/* TODO store inherited data, e.g. status first, but mark them somehow to allow to overwrite them and not detect duplicity */
+ /* note into the compile context that we are processing extension now */
+ ctx->ext = ext;
+
/* keep order of the processing the same as the order in the defined substmts,
* the order is important for some of the statements depending on others (e.g. type needs status and units) */
- LY_ARRAY_FOR(substmts, u) {
- ly_bool stmt_present = 0;
- for (stmt = ext->child; stmt; stmt = stmt->next) {
- if (substmts[u].stmt != stmt->kw) {
+ LY_ARRAY_FOR(ext->substmts, u) {
+ uint64_t stmt_counter = 0;
+
+ for (stmt = ext_p->child; stmt; stmt = stmt->next) {
+ if (ext->substmts[u].stmt != stmt->kw) {
continue;
}
- stmt_present = 1;
- if (substmts[u].storage) {
+ parsed = NULL;
+ stmt_counter++;
+ if (ext->substmts[u].storage) {
switch (stmt->kw) {
- case LY_STMT_STATUS:
- assert(substmts[u].cardinality < LY_STMT_CARD_SOME);
- LY_CHECK_ERR_GOTO(r = lysp_stmt_parse(ctx, stmt, &substmts[u].storage, /* TODO */ NULL), ret = r, cleanup);
+ case LY_STMT_ACTION:
+ case LY_STMT_ANYDATA:
+ case LY_STMT_ANYXML:
+ case LY_STMT_CONTAINER:
+ case LY_STMT_CHOICE:
+ case LY_STMT_LEAF:
+ case LY_STMT_LEAF_LIST:
+ case LY_STMT_LIST:
+ case LY_STMT_NOTIFICATION:
+ case LY_STMT_RPC:
+ case LY_STMT_USES:
+ r = lysp_stmt_parse(ctx, stmt, &parsed, NULL);
+ LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
+
+ /* set storage as an alternative document root in the compile context */
+ r = lys_compile_node(ctx, parsed, NULL, 0, NULL);
+ lysp_node_free(ctx->ctx, parsed);
+ LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
break;
case LY_STMT_DESCRIPTION:
case LY_STMT_REFERENCE:
case LY_STMT_UNITS: {
- const char **units;
+ const char **str_p;
- if (substmts[u].cardinality < LY_STMT_CARD_SOME) {
+ if (ext->substmts[u].cardinality < LY_STMT_CARD_SOME) {
/* single item */
- if (*((const char **)substmts[u].storage)) {
+ if (*((const char **)ext->substmts[u].storage)) {
LOGVAL(ctx->ctx, LY_VCODE_DUPSTMT, stmt->stmt);
goto cleanup;
}
- units = (const char **)substmts[u].storage;
+ str_p = (const char **)ext->substmts[u].storage;
} else {
/* sized array */
- const char ***units_array = (const char ***)substmts[u].storage;
- LY_ARRAY_NEW_GOTO(ctx->ctx, *units_array, units, ret, cleanup);
+ const char ***strings_array = (const char ***)ext->substmts[u].storage;
+ LY_ARRAY_NEW_GOTO(ctx->ctx, *strings_array, str_p, ret, cleanup);
}
- r = lydict_insert(ctx->ctx, stmt->arg, 0, units);
+ r = lydict_insert(ctx->ctx, stmt->arg, 0, str_p);
LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
break;
}
- case LY_STMT_TYPE: {
- uint16_t *flags = lys_compile_extension_instance_storage(LY_STMT_STATUS, substmts);
- const char **units = lys_compile_extension_instance_storage(LY_STMT_UNITS, substmts);
-
- if (substmts[u].cardinality < LY_STMT_CARD_SOME) {
- /* single item */
- if (*(struct lysc_type **)substmts[u].storage) {
- LOGVAL(ctx->ctx, LY_VCODE_DUPSTMT, stmt->stmt);
- goto cleanup;
- }
- compiled = substmts[u].storage;
- } else {
- /* sized array */
- struct lysc_type ***types = (struct lysc_type ***)substmts[u].storage, **type = NULL;
- LY_ARRAY_NEW_GOTO(ctx->ctx, *types, type, ret, cleanup);
- compiled = (void *)type;
- }
+ case LY_STMT_IF_FEATURE: {
+ ly_bool enabled;
r = lysp_stmt_parse(ctx, stmt, &parsed, NULL);
LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
- r = lys_compile_type(ctx, NULL, flags ? *flags : 0, ext->name, parsed, (struct lysc_type **)compiled,
- units && !*units ? units : NULL, NULL);
- lysp_type_free(ctx->ctx, parsed);
- free(parsed);
- LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
- break;
- }
- case LY_STMT_IF_FEATURE:
- iffeatures = NULL;
- LY_ARRAY_NEW_GOTO(ctx->ctx, iffeatures, iffeat, ret, cleanup);
- iffeat->str = stmt->arg;
- iffeat->mod = ctx->pmod;
- r = lys_eval_iffeatures(ctx->ctx, iffeatures, &enabled);
- LY_ARRAY_FREE(iffeatures);
+
+ r = lys_eval_iffeatures(ctx->ctx, parsed, &enabled);
+ FREE_ARRAY(ctx->ctx, (struct lysp_qname *)parsed, lysp_qname_free);
LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
if (!enabled) {
/* it is disabled, remove the whole extension instance */
return LY_ENOT;
}
break;
+ }
+ case LY_STMT_STATUS:
+ assert(ext->substmts[u].cardinality < LY_STMT_CARD_SOME);
+ LY_CHECK_ERR_GOTO(r = lysp_stmt_parse(ctx, stmt, &ext->substmts[u].storage, /* TODO */ NULL), ret = r, cleanup);
+ break;
+ case LY_STMT_TYPE: {
+ uint16_t *flags = lys_compile_extension_instance_storage(LY_STMT_STATUS, ext->substmts);
+ const char **units = lys_compile_extension_instance_storage(LY_STMT_UNITS, ext->substmts);
+
+ if (ext->substmts[u].cardinality < LY_STMT_CARD_SOME) {
+ /* single item */
+ if (*(struct lysc_type **)ext->substmts[u].storage) {
+ LOGVAL(ctx->ctx, LY_VCODE_DUPSTMT, stmt->stmt);
+ goto cleanup;
+ }
+ compiled = ext->substmts[u].storage;
+ } else {
+ /* sized array */
+ struct lysc_type ***types = (struct lysc_type ***)ext->substmts[u].storage, **type = NULL;
+ LY_ARRAY_NEW_GOTO(ctx->ctx, *types, type, ret, cleanup);
+ compiled = (void *)type;
+ }
+
+ r = lysp_stmt_parse(ctx, stmt, &parsed, NULL);
+ LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
+ r = lys_compile_type(ctx, NULL, flags ? *flags : 0, ext_p->name, parsed, (struct lysc_type **)compiled,
+ units && !*units ? units : NULL, NULL);
+ lysp_type_free(ctx->ctx, parsed);
+ free(parsed);
+ LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
+ break;
+ }
/* TODO support other substatements (parse stmt to lysp and then compile lysp to lysc),
* also note that in many statements their extensions are not taken into account */
default:
LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Statement \"%s\" is not supported as an extension (found in \"%s%s%s\") substatement.",
- stmt->stmt, ext->name, ext->argument ? " " : "", ext->argument ? ext->argument : "");
+ stmt->stmt, ext_p->name, ext_p->argument ? " " : "", ext_p->argument ? ext_p->argument : "");
goto cleanup;
}
}
}
- if (((substmts[u].cardinality == LY_STMT_CARD_MAND) || (substmts[u].cardinality == LY_STMT_CARD_SOME)) && !stmt_present) {
+ if (((ext->substmts[u].cardinality == LY_STMT_CARD_MAND) || (ext->substmts[u].cardinality == LY_STMT_CARD_SOME)) && !stmt_counter) {
LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Missing mandatory keyword \"%s\" as a child of \"%s%s%s\".",
- ly_stmt2str(substmts[u].stmt), ext->name, ext->argument ? " " : "", ext->argument ? ext->argument : "");
+ ly_stmt2str(ext->substmts[u].stmt), ext_p->name, ext_p->argument ? " " : "", ext_p->argument ? ext_p->argument : "");
goto cleanup;
}
}
@@ -745,6 +769,7 @@
ret = LY_SUCCESS;
cleanup:
+ ctx->ext = NULL;
return ret;
}
diff --git a/src/schema_compile.h b/src/schema_compile.h
index 335059c..15683e0 100644
--- a/src/schema_compile.h
+++ b/src/schema_compile.h
@@ -67,6 +67,8 @@
- augment - module where the augment is defined
- deviation - module where the deviation is defined
- uses - module where the grouping is defined */
+ struct lysc_ext_instance *ext; /**< extension instance being processed and serving as a source for its substatements
+ instead of the module itself */
struct ly_set groupings; /**< stack for groupings circular check */
struct ly_set tpdf_chain;
struct ly_set disabled; /**< set of compiled nodes whose if-feature(s) was not satisifed */
diff --git a/src/schema_compile_node.c b/src/schema_compile_node.c
index 6755377..1b00161 100644
--- a/src/schema_compile_node.c
+++ b/src/schema_compile_node.c
@@ -2201,7 +2201,9 @@
/* top-level element */
struct lysc_node **list;
- if (node->nodetype == LYS_RPC) {
+ if (ctx->ext) {
+ lysc_ext_substmt(ctx->ext, LY_STMT_CONTAINER /* matches all data nodes */, (void **)&list, NULL);
+ } else if (node->nodetype == LYS_RPC) {
list = (struct lysc_node **)&ctx->cur_mod->compiled->rpcs;
} else if (node->nodetype == LYS_NOTIF) {
list = (struct lysc_node **)&ctx->cur_mod->compiled->notifs;
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 1e7cd02..d798b5b 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -38,6 +38,7 @@
#include "parser_internal.h"
#include "parser_schema.h"
#include "path.h"
+#include "plugins_exts.h"
#include "schema_compile.h"
#include "schema_compile_amend.h"
#include "schema_features.h"
@@ -51,81 +52,81 @@
* @brief information about YANG statements
*/
struct stmt_info_s stmt_attr_info[] = {
- {NULL, NULL, 0}, /**< LY_STMT_NONE */
- {"action", "name", STMT_FLAG_ID}, /**< LY_STMT_ACTION */
- {"anydata", "name", STMT_FLAG_ID}, /**< LY_STMT_ANYDATA */
- {"anyxml", "name", STMT_FLAG_ID}, /**< LY_STMT_ANYXML */
- {"argument", "name", STMT_FLAG_ID}, /**< LY_STMT_ARGUMENT */
- {"text", NULL, 0}, /**< LY_STMT_ARG_TEXT */
- {"value", NULL, 0}, /**< LY_STMT_ARG_VALUE */
- {"augment", "target-node", STMT_FLAG_ID}, /**< LY_STMT_AUGMENT */
- {"base", "name", STMT_FLAG_ID}, /**< LY_STMT_BASE */
- {"belongs-to", "module", STMT_FLAG_ID}, /**< LY_STMT_BELONGS_TO */
- {"bit", "name", STMT_FLAG_ID}, /**< LY_STMT_BIT */
- {"case", "name", STMT_FLAG_ID}, /**< LY_STMT_CASE */
- {"choice", "name", STMT_FLAG_ID}, /**< LY_STMT_CHOICE */
- {"config", "value", STMT_FLAG_ID}, /**< LY_STMT_CONFIG */
- {"contact", "text", STMT_FLAG_YIN},/**< LY_STMT_CONTACT */
- {"container", "name", STMT_FLAG_ID}, /**< LY_STMT_CONTAINER */
- {"default", "value", 0}, /**< LY_STMT_DEFAULT */
- {"description", "text", STMT_FLAG_YIN},/**< LY_STMT_DESCRIPTION */
- {"deviate", "value", STMT_FLAG_ID}, /**< LY_STMT_DEVIATE */
- {"deviation", "target-node", STMT_FLAG_ID}, /**< LY_STMT_DEVIATION */
- {"enum", "name", STMT_FLAG_ID}, /**< LY_STMT_ENUM */
- {"error-app-tag", "value", 0}, /**< LY_STMT_ERRTAG */
- {"error-message", "value", STMT_FLAG_YIN},/**< LY_STMT_ERRMSG */
- {"extension", "name", STMT_FLAG_ID}, /**< LY_STMT_EXTENSION */
- {NULL, NULL, 0}, /**< LY_STMT_EXTENSION_INSTANCE */
- {"feature", "name", STMT_FLAG_ID}, /**< LY_STMT_FEATURE */
- {"fraction-digits", "value", STMT_FLAG_ID}, /**< LY_STMT_FRACTION_DIGITS */
- {"grouping", "name", STMT_FLAG_ID}, /**< LY_STMT_GROUPING */
- {"identity", "name", STMT_FLAG_ID}, /**< LY_STMT_IDENTITY */
- {"if-feature", "name", 0}, /**< LY_STMT_IF_FEATURE */
- {"import", "module", STMT_FLAG_ID}, /**< LY_STMT_IMPORT */
- {"include", "module", STMT_FLAG_ID}, /**< LY_STMT_INCLUDE */
- {"input", NULL, 0}, /**< LY_STMT_INPUT */
- {"key", "value", 0}, /**< LY_STMT_KEY */
- {"leaf", "name", STMT_FLAG_ID}, /**< LY_STMT_LEAF */
- {"leaf-list", "name", STMT_FLAG_ID}, /**< LY_STMT_LEAF_LIST */
- {"length", "value", 0}, /**< LY_STMT_LENGTH */
- {"list", "name", STMT_FLAG_ID}, /**< LY_STMT_LIST */
- {"mandatory", "value", STMT_FLAG_ID}, /**< LY_STMT_MANDATORY */
- {"max-elements", "value", STMT_FLAG_ID}, /**< LY_STMT_MAX_ELEMENTS */
- {"min-elements", "value", STMT_FLAG_ID}, /**< LY_STMT_MIN_ELEMENTS */
- {"modifier", "value", STMT_FLAG_ID}, /**< LY_STMT_MODIFIER */
- {"module", "name", STMT_FLAG_ID}, /**< LY_STMT_MODULE */
- {"must", "condition", 0}, /**< LY_STMT_MUST */
- {"namespace", "uri", 0}, /**< LY_STMT_NAMESPACE */
- {"notification", "name", STMT_FLAG_ID}, /**< LY_STMT_NOTIFICATION */
- {"ordered-by", "value", STMT_FLAG_ID}, /**< LY_STMT_ORDERED_BY */
- {"organization", "text", STMT_FLAG_YIN},/**< LY_STMT_ORGANIZATION */
- {"output", NULL, 0}, /**< LY_STMT_OUTPUT */
- {"path", "value", 0}, /**< LY_STMT_PATH */
- {"pattern", "value", 0}, /**< LY_STMT_PATTERN */
- {"position", "value", STMT_FLAG_ID}, /**< LY_STMT_POSITION */
- {"prefix", "value", STMT_FLAG_ID}, /**< LY_STMT_PREFIX */
- {"presence", "value", 0}, /**< LY_STMT_PRESENCE */
- {"range", "value", 0}, /**< LY_STMT_RANGE */
- {"reference", "text", STMT_FLAG_YIN},/**< LY_STMT_REFERENCE */
- {"refine", "target-node", STMT_FLAG_ID}, /**< LY_STMT_REFINE */
- {"require-instance", "value", STMT_FLAG_ID}, /**< LY_STMT_REQUIRE_INSTANCE */
- {"revision", "date", STMT_FLAG_ID}, /**< LY_STMT_REVISION */
- {"revision-date", "date", STMT_FLAG_ID}, /**< LY_STMT_REVISION_DATE */
- {"rpc", "name", STMT_FLAG_ID}, /**< LY_STMT_RPC */
- {"status", "value", STMT_FLAG_ID}, /**< LY_STMT_STATUS */
- {"submodule", "name", STMT_FLAG_ID}, /**< LY_STMT_SUBMODULE */
- {"{", NULL, 0}, /**< LY_STMT_SYNTAX_LEFT_BRACE */
- {"}", NULL, 0}, /**< LY_STMT_SYNTAX_RIGHT_BRACE */
- {";", NULL, 0}, /**< LY_STMT_SYNTAX_SEMICOLON */
- {"type", "name", STMT_FLAG_ID}, /**< LY_STMT_TYPE */
- {"typedef", "name", STMT_FLAG_ID}, /**< LY_STMT_TYPEDEF */
- {"unique", "tag", 0}, /**< LY_STMT_UNIQUE */
- {"units", "name", 0}, /**< LY_STMT_UNITS */
- {"uses", "name", STMT_FLAG_ID}, /**< LY_STMT_USES */
- {"value", "value", STMT_FLAG_ID}, /**< LY_STMT_VALUE */
- {"when", "condition", 0}, /**< LY_STMT_WHEN */
- {"yang-version", "value", STMT_FLAG_ID}, /**< LY_STMT_YANG_VERSION */
- {"yin-element", "value", STMT_FLAG_ID}, /**< LY_STMT_YIN_ELEMENT */
+ [LY_STMT_NONE] = {NULL, NULL, 0},
+ [LY_STMT_ACTION] = {"action", "name", STMT_FLAG_ID},
+ [LY_STMT_ANYDATA] = {"anydata", "name", STMT_FLAG_ID},
+ [LY_STMT_ANYXML] = {"anyxml", "name", STMT_FLAG_ID},
+ [LY_STMT_ARGUMENT] = {"argument", "name", STMT_FLAG_ID},
+ [LY_STMT_ARG_TEXT] = {"text", NULL, 0},
+ [LY_STMT_ARG_VALUE] = {"value", NULL, 0},
+ [LY_STMT_AUGMENT] = {"augment", "target-node", STMT_FLAG_ID},
+ [LY_STMT_BASE] = {"base", "name", STMT_FLAG_ID},
+ [LY_STMT_BELONGS_TO] = {"belongs-to", "module", STMT_FLAG_ID},
+ [LY_STMT_BIT] = {"bit", "name", STMT_FLAG_ID},
+ [LY_STMT_CASE] = {"case", "name", STMT_FLAG_ID},
+ [LY_STMT_CHOICE] = {"choice", "name", STMT_FLAG_ID},
+ [LY_STMT_CONFIG] = {"config", "value", STMT_FLAG_ID},
+ [LY_STMT_CONTACT] = {"contact", "text", STMT_FLAG_YIN},
+ [LY_STMT_CONTAINER] = {"container", "name", STMT_FLAG_ID},
+ [LY_STMT_DEFAULT] = {"default", "value", 0},
+ [LY_STMT_DESCRIPTION] = {"description", "text", STMT_FLAG_YIN},
+ [LY_STMT_DEVIATE] = {"deviate", "value", STMT_FLAG_ID},
+ [LY_STMT_DEVIATION] = {"deviation", "target-node", STMT_FLAG_ID},
+ [LY_STMT_ENUM] = {"enum", "name", STMT_FLAG_ID},
+ [LY_STMT_ERROR_APP_TAG] = {"error-app-tag", "value", 0},
+ [LY_STMT_ERROR_MESSAGE] = {"error-message", "value", STMT_FLAG_YIN},
+ [LY_STMT_EXTENSION] = {"extension", "name", STMT_FLAG_ID},
+ [LY_STMT_EXTENSION_INSTANCE] = {NULL, NULL, 0},
+ [LY_STMT_FEATURE] = {"feature", "name", STMT_FLAG_ID},
+ [LY_STMT_FRACTION_DIGITS] = {"fraction-digits", "value", STMT_FLAG_ID},
+ [LY_STMT_GROUPING] = {"grouping", "name", STMT_FLAG_ID},
+ [LY_STMT_IDENTITY] = {"identity", "name", STMT_FLAG_ID},
+ [LY_STMT_IF_FEATURE] = {"if-feature", "name", 0},
+ [LY_STMT_IMPORT] = {"import", "module", STMT_FLAG_ID},
+ [LY_STMT_INCLUDE] = {"include", "module", STMT_FLAG_ID},
+ [LY_STMT_INPUT] = {"input", NULL, 0},
+ [LY_STMT_KEY] = {"key", "value", 0},
+ [LY_STMT_LEAF] = {"leaf", "name", STMT_FLAG_ID},
+ [LY_STMT_LEAF_LIST] = {"leaf-list", "name", STMT_FLAG_ID},
+ [LY_STMT_LENGTH] = {"length", "value", 0},
+ [LY_STMT_LIST] = {"list", "name", STMT_FLAG_ID},
+ [LY_STMT_MANDATORY] = {"mandatory", "value", STMT_FLAG_ID},
+ [LY_STMT_MAX_ELEMENTS] = {"max-elements", "value", STMT_FLAG_ID},
+ [LY_STMT_MIN_ELEMENTS] = {"min-elements", "value", STMT_FLAG_ID},
+ [LY_STMT_MODIFIER] = {"modifier", "value", STMT_FLAG_ID},
+ [LY_STMT_MODULE] = {"module", "name", STMT_FLAG_ID},
+ [LY_STMT_MUST] = {"must", "condition", 0},
+ [LY_STMT_NAMESPACE] = {"namespace", "uri", 0},
+ [LY_STMT_NOTIFICATION] = {"notification", "name", STMT_FLAG_ID},
+ [LY_STMT_ORDERED_BY] = {"ordered-by", "value", STMT_FLAG_ID},
+ [LY_STMT_ORGANIZATION] = {"organization", "text", STMT_FLAG_YIN},
+ [LY_STMT_OUTPUT] = {"output", NULL, 0},
+ [LY_STMT_PATH] = {"path", "value", 0},
+ [LY_STMT_PATTERN] = {"pattern", "value", 0},
+ [LY_STMT_POSITION] = {"position", "value", STMT_FLAG_ID},
+ [LY_STMT_PREFIX] = {"prefix", "value", STMT_FLAG_ID},
+ [LY_STMT_PRESENCE] = {"presence", "value", 0},
+ [LY_STMT_RANGE] = {"range", "value", 0},
+ [LY_STMT_REFERENCE] = {"reference", "text", STMT_FLAG_YIN},
+ [LY_STMT_REFINE] = {"refine", "target-node", STMT_FLAG_ID},
+ [LY_STMT_REQUIRE_INSTANCE] = {"require-instance", "value", STMT_FLAG_ID},
+ [LY_STMT_REVISION] = {"revision", "date", STMT_FLAG_ID},
+ [LY_STMT_REVISION_DATE] = {"revision-date", "date", STMT_FLAG_ID},
+ [LY_STMT_RPC] = {"rpc", "name", STMT_FLAG_ID},
+ [LY_STMT_STATUS] = {"status", "value", STMT_FLAG_ID},
+ [LY_STMT_SUBMODULE] = {"submodule", "name", STMT_FLAG_ID},
+ [LY_STMT_SYNTAX_LEFT_BRACE] = {"{", NULL, 0},
+ [LY_STMT_SYNTAX_RIGHT_BRACE] = {"}", NULL, 0},
+ [LY_STMT_SYNTAX_SEMICOLON] = {";", NULL, 0},
+ [LY_STMT_TYPE] = {"type", "name", STMT_FLAG_ID},
+ [LY_STMT_TYPEDEF] = {"typedef", "name", STMT_FLAG_ID},
+ [LY_STMT_UNIQUE] = {"unique", "tag", 0},
+ [LY_STMT_UNITS] = {"units", "name", 0},
+ [LY_STMT_USES] = {"uses", "name", STMT_FLAG_ID},
+ [LY_STMT_VALUE] = {"value", "value", STMT_FLAG_ID},
+ [LY_STMT_WHEN] = {"when", "condition", 0},
+ [LY_STMT_YANG_VERSION] = {"yang-version", "value", STMT_FLAG_ID},
+ [LY_STMT_YIN_ELEMENT] = {"yin-element", "value", STMT_FLAG_ID},
};
const char * const ly_devmod_list[] = {
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 546c587..817e27e 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -251,37 +251,93 @@
#define LYS_NODETYPE_MASK 0xffff /**< Mask for nodetypes, the value is limited for 16 bits */
/**
+ * @brief Generic test for operation (RPC or Action) statements.
+ */
+#define LY_STMT_IS_OP(STMT) (((STMT) == LY_STMT_ACTION) || ((STMT) == LY_STMT_RPC))
+
+/**
+ * @brief Generic test for schema node (anydata, anyxml, augment, case, choice, container, grouping,
+ * leaf, leaf-list, list and uses) statements.
+ *
+ * Covers the statements that maps to a common ::lysc_node or ::lysp_node structures. Note that the
+ * list of statements that can appear in parsed or compiled schema trees differs (e.g. no uses in compiled tree).
+ *
+ * The operations (action/RPC) and notification statements are not included since they are used to be stored
+ * in a separated lists in schema node structures.
+ */
+#define LY_STMT_IS_NODE(STMT) (((STMT) >= LY_STMT_ANYDATA) && ((STMT) <= LY_STMT_LIST))
+
+/**
* @brief List of YANG statements
*/
enum ly_stmt {
LY_STMT_NONE = 0,
+
+ LY_STMT_NOTIFICATION, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node_notif *`.
+ The RPCs/Actions and Notifications are expected in a separated lists than the rest of
+ data definition nodes as it is done in generic structures of libyang. */
+
+/* LY_STMT_IS_OP */
LY_STMT_ACTION, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node_action *`.
- Note that due to compatibility with `struct lysc_node *`, the compiled actions can be actually
- mixed in the linked list with other ::lysc_node based nodes if the storage is shared. */
+ The RPCs/Actions and Notifications are expected in a separated lists than the rest of
+ data definition nodes as it is done in generic structures of libyang. */
+ LY_STMT_RPC, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node_action *`.
+ The RPCs/Actions and Notifications are expected in a separated lists than the rest of
+ data definition nodes as it is done in generic structures of libyang. */
+
+/* LY_STMT_IS_NODE */
LY_STMT_ANYDATA, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node *`.
- Note that due to ::lysc_node compatibility the anydata can be actually mixed in
- the linked list with other ::lysc_node based nodes if the storage is shared. */
+ Note that due to ::lysc_node compatibility the anydata is expected to be actually
+ mixed in the linked list with other ::lysc_node based nodes. The RPCs/Actions and
+ Notifications are expected in a separated lists as it is done in generic structures
+ of libyang. */
LY_STMT_ANYXML, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node *`.
- Note that due to ::lysc_node compatibility the anyxml can be actually mixed in
- the linked list with other ::lysc_node based nodes if the storage is shared. */
+ Note that due to ::lysc_node compatibility the anyxml is expected to be actually
+ mixed in the linked list with other ::lysc_node based nodes. The RPCs/Actions and
+ Notifications are expected in a separated lists as it is done in generic structures
+ of libyang. */
+ LY_STMT_AUGMENT,
+ LY_STMT_CASE, /**< TODO is it possible to compile cases without the parent choice? */
+ LY_STMT_CHOICE, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node *`.
+ Note that due to ::lysc_node compatibility the choice is expected to be actually
+ mixed in the linked list with other ::lysc_node based nodes. The RPCs/Actions and
+ Notifications are expected in a separated lists as it is done in generic structures
+ of libyang. */
+ LY_STMT_CONTAINER, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node *`.
+ Note that due to ::lysc_node compatibility the container is expected to be actually
+ mixed in the linked list with other ::lysc_node based nodes. The RPCs/Actions and
+ Notifications are expected in a separated lists as it is done in generic structures
+ of libyang. */
+ LY_STMT_GROUPING,
+ LY_STMT_LEAF, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node *`.
+ Note that due to ::lysc_node compatibility the leaf is expected to be actually
+ mixed in the linked list with other ::lysc_node based nodes. The RPCs/Actions and
+ Notifications are expected in a separated lists as it is done in generic structures
+ of libyang. */
+ LY_STMT_LEAF_LIST, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node *`.
+ Note that due to ::lysc_node compatibility the leaf-list is expected to be actually
+ mixed in the linked list with other ::lysc_node based nodes. The RPCs/Actions and
+ Notifications are expected in a separated lists as it is done in generic structures
+ of libyang. */
+ LY_STMT_LIST, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node *`.
+ Note that due to ::lysc_node compatibility the list is expected to be actually
+ mixed in the linked list with other ::lysc_node based nodes. The RPCs/Actions and
+ Notifications are expected in a separated lists as it is done in generic structures
+ of libyang. */
+ LY_STMT_USES,
+
+/* rest */
LY_STMT_ARGUMENT,
LY_STMT_ARG_TEXT,
LY_STMT_ARG_VALUE,
- LY_STMT_AUGMENT,
LY_STMT_BASE,
LY_STMT_BELONGS_TO,
LY_STMT_BIT,
- LY_STMT_CASE, /**< TODO is it possible to compile cases without the parent choice? */
- LY_STMT_CHOICE, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node *`.
- Note that due to ::lysc_node compatibility the choice can be actually mixed in
- the linked list with other ::lysc_node based nodes if the storage is shared. */
LY_STMT_CONFIG, /**< in ::lysc_ext_substmt.storage stored as a pointer to `uint16_t`, only cardinality < #LY_STMT_CARD_SOME is allowed */
LY_STMT_CONTACT,
- LY_STMT_CONTAINER, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node *`.
- Note that due to ::lysc_node compatibility the container can be actually mixed in
- the linked list with other ::lysc_node based nodes if the storage is shared. */
LY_STMT_DEFAULT,
- LY_STMT_DESCRIPTION,
+ LY_STMT_DESCRIPTION, /**< in ::lysc_ext_substmt.storage stored as a pointer to `const char *` (cardinality < #LY_STMT_CARD_SOME)
+ or as a pointer to a [sized array](@ref sizedarrays) `const char **` */
LY_STMT_DEVIATE,
LY_STMT_DEVIATION,
LY_STMT_ENUM,
@@ -291,20 +347,15 @@
LY_STMT_EXTENSION_INSTANCE,
LY_STMT_FEATURE,
LY_STMT_FRACTION_DIGITS,
- LY_STMT_GROUPING,
LY_STMT_IDENTITY,
- LY_STMT_IF_FEATURE, /**< in ::lysc_ext_substmt.storage stored as a pointer to `struct lysc_iffeature` (cardinality < #LY_STMT_CARD_SOME)
- or as a pointer to a [sized array](@ref sizedarrays) `struct lysc_iffeature *` */
+ LY_STMT_IF_FEATURE, /**< if-feature statements are not compiled, they are evaluated and the parent statement is
+ preserved only in case the evaluation of all the if-feature statements is true.
+ Therefore there is no storage expected. */
LY_STMT_IMPORT,
LY_STMT_INCLUDE,
LY_STMT_INPUT,
LY_STMT_KEY,
- LY_STMT_LEAF,
- LY_STMT_LEAF_LIST,
LY_STMT_LENGTH,
- LY_STMT_LIST, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node *`.
- Note that due to ::lysc_node compatibility the list can be actually mixed in
- the linked list with other ::lysc_node based nodes if the storage is shared. */
LY_STMT_MANDATORY, /**< in ::lysc_ext_substmt.storage stored as a pointer to `uint16_t`, only cardinality < #LY_STMT_CARD_SOME is allowed */
LY_STMT_MAX_ELEMENTS,
LY_STMT_MIN_ELEMENTS,
@@ -312,7 +363,6 @@
LY_STMT_MODULE,
LY_STMT_MUST,
LY_STMT_NAMESPACE,
- LY_STMT_NOTIFICATION,
LY_STMT_ORDERED_BY,
LY_STMT_ORGANIZATION,
LY_STMT_OUTPUT,
@@ -322,14 +372,12 @@
LY_STMT_PREFIX,
LY_STMT_PRESENCE,
LY_STMT_RANGE,
- LY_STMT_REFERENCE,
+ LY_STMT_REFERENCE, /**< in ::lysc_ext_substmt.storage stored as a pointer to `const char *` (cardinality < #LY_STMT_CARD_SOME)
+ or as a pointer to a [sized array](@ref sizedarrays) `const char **` */
LY_STMT_REFINE,
LY_STMT_REQUIRE_INSTANCE,
LY_STMT_REVISION,
LY_STMT_REVISION_DATE,
- LY_STMT_RPC, /**< in ::lysc_ext_substmt.storage stored as a pointer to linked list of `struct lysc_node_action *`.
- Note that due to compatibility with `struct lysc_node *`, the compiled RPCs can be actually
- mixed in the linked list with other ::lysc_node based nodes if the storage is shared. */
LY_STMT_STATUS, /**< in ::lysc_ext_substmt.storage stored as a pointer to `uint16_t`, only cardinality < #LY_STMT_CARD_SOME is allowed */
LY_STMT_SUBMODULE,
LY_STMT_SYNTAX_SEMICOLON,
@@ -341,7 +389,6 @@
LY_STMT_UNIQUE,
LY_STMT_UNITS, /**< in ::lysc_ext_substmt.storage stored as a pointer to `const char *` (cardinality < #LY_STMT_CARD_SOME)
or as a pointer to a [sized array](@ref sizedarrays) `const char **` */
- LY_STMT_USES,
LY_STMT_VALUE,
LY_STMT_WHEN,
LY_STMT_YANG_VERSION,
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index 8bcfb5a..7690c98 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -997,23 +997,28 @@
}
switch (substmts[u].stmt) {
- case LY_STMT_TYPE:
- if (substmts[u].cardinality < LY_STMT_CARD_SOME) {
- /* single item */
- struct lysc_type *type = *((struct lysc_type **)substmts[u].storage);
- if (!type) {
- break;
- }
- lysc_type_free(ctx, type);
- } else {
- /* multiple items */
- struct lysc_type **types = *((struct lysc_type ***)substmts[u].storage);
- if (!types) {
- break;
- }
- FREE_ARRAY(ctx, types, lysc_type2_free);
+ case LY_STMT_ACTION:
+ case LY_STMT_ANYDATA:
+ case LY_STMT_ANYXML:
+ case LY_STMT_CONTAINER:
+ case LY_STMT_CHOICE:
+ case LY_STMT_LEAF:
+ case LY_STMT_LEAF_LIST:
+ case LY_STMT_LIST:
+ case LY_STMT_NOTIFICATION:
+ case LY_STMT_RPC:
+ case LY_STMT_USES: {
+ struct lysc_node *child, *child_next;
+
+ LY_LIST_FOR_SAFE(*((struct lysc_node **)substmts[u].storage), child_next, child) {
+ lysc_node_free_(ctx, child);
}
break;
+ }
+ case LY_STMT_CONFIG:
+ case LY_STMT_STATUS:
+ /* nothing to do */
+ break;
case LY_STMT_DESCRIPTION:
case LY_STMT_REFERENCE:
case LY_STMT_UNITS:
@@ -1033,10 +1038,6 @@
FREE_STRINGS(ctx, strs);
}
break;
- case LY_STMT_STATUS:
- case LY_STMT_CONFIG:
- /* nothing to do */
- break;
case LY_STMT_IF_FEATURE: {
struct lysc_iffeature *iff = *((struct lysc_iffeature **)substmts[u].storage);
if (!iff) {
@@ -1051,6 +1052,23 @@
FREE_ARRAY(ctx, iff, lysc_iffeature_free);
}
break;
+ case LY_STMT_TYPE:
+ if (substmts[u].cardinality < LY_STMT_CARD_SOME) {
+ /* single item */
+ struct lysc_type *type = *((struct lysc_type **)substmts[u].storage);
+ if (!type) {
+ break;
+ }
+ lysc_type_free(ctx, type);
+ } else {
+ /* multiple items */
+ struct lysc_type **types = *((struct lysc_type ***)substmts[u].storage);
+ if (!types) {
+ break;
+ }
+ FREE_ARRAY(ctx, types, lysc_type2_free);
+ }
+ break;
}
/* TODO other statements */