schema compilation CHANGE basic support for compiling nodes
Starting with container, not complete, just basic mechanism.
diff --git a/src/tree_schema.c b/src/tree_schema.c
index d64768e..6b1dd16 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -36,7 +36,7 @@
#define COMPILE_ARRAY_GOTO(CTX, ARRAY_P, ARRAY_C, OPTIONS, ITER, FUNC, RET, GOTO) \
if (ARRAY_P) { \
- LY_ARRAY_CREATE_GOTO((CTX)->mod->ctx, ARRAY_C, LY_ARRAY_SIZE(ARRAY_P), RET, GOTO); \
+ LY_ARRAY_CREATE_GOTO((CTX)->ctx, ARRAY_C, LY_ARRAY_SIZE(ARRAY_P), RET, GOTO); \
for (ITER = 0; ITER < LY_ARRAY_SIZE(ARRAY_P); ++ITER) { \
LY_ARRAY_INCREMENT(ARRAY_C); \
RET = FUNC(CTX, &(ARRAY_P)[ITER], OPTIONS, &(ARRAY_C)[ITER]); \
@@ -47,9 +47,10 @@
static void lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp, int dict);
static void lysp_node_free(struct ly_ctx *ctx, struct lysp_node *node, int dict);
-#define LYSC_CTX_BUFSIZE 4086
+#define LYSC_CTX_BUFSIZE 4078
struct lysc_ctx {
- struct lysc_module *mod;
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
uint16_t path_len;
char path[LYSC_CTX_BUFSIZE];
};
@@ -504,10 +505,41 @@
FREE_ARRAY(ctx, feat->exts, lysc_ext_instance_free);
}
+static void lysc_node_free(struct ly_ctx *ctx, struct lysc_node *node, int dict);
+
+static void
+lysc_node_container_free(struct ly_ctx *ctx, struct lysc_node_container *node, int dict)
+{
+ struct lysc_node *child, *child_next;
+
+ LY_LIST_FOR_SAFE(node->child, child_next, child) {
+ lysc_node_free(ctx, child, dict);
+ }
+}
+
+static void
+lysc_node_free(struct ly_ctx *ctx, struct lysc_node *node, int dict)
+{
+ /* common part */
+ FREE_STRING(ctx, node->name, dict);
+
+ /* nodetype-specific part */
+ switch(node->nodetype) {
+ case LYS_CONTAINER:
+ lysc_node_container_free(ctx, (struct lysc_node_container*)node, dict);
+ break;
+ default:
+ LOGINT(ctx);
+ }
+
+ free(node);
+}
+
static void
lysc_module_free_(struct lysc_module *module, int dict)
{
struct ly_ctx *ctx;
+ struct lysc_node *node, *node_next;
LY_CHECK_ARG_RET(NULL, module,);
ctx = module->ctx;
@@ -521,6 +553,10 @@
FREE_ARRAY(ctx, module->features, lysc_feature_free);
FREE_ARRAY(ctx, module->identities, lysc_ident_free);
+ LY_LIST_FOR_SAFE(module->data, node_next, node) {
+ lysc_node_free(ctx, node, dict);
+ }
+
FREE_ARRAY(ctx, module->exts, lysc_ext_instance_free);
free(module);
@@ -892,19 +928,19 @@
ext->argument = ext_p->argument;
} else {
/* keep refcounts correct for lysp_module_free() */
- ext->argument = lydict_insert(ctx->mod->ctx, ext_p->argument, 0);
+ ext->argument = lydict_insert(ctx->ctx, ext_p->argument, 0);
}
ext->insubstmt = ext_p->insubstmt;
ext->insubstmt_index = ext_p->insubstmt_index;
/* get module where the extension definition should be placed */
for (u = 0; ext_p->name[u] != ':'; ++u);
- mod = lysc_module_find_prefix(ctx->mod, ext_p->name, u);
- LY_CHECK_ERR_RET(!mod, LOGVAL(ctx->mod->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
+ mod = lys_module_find_prefix(ctx->mod, ext_p->name, u);
+ LY_CHECK_ERR_RET(!mod, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
"Invalid prefix \"%.*s\" used for extension instance identifier.", u, ext_p->name),
LY_EVALID);
LY_CHECK_ERR_RET(!mod->parsed->extensions,
- LOGVAL(ctx->mod->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
"Extension instance \"%s\" refers \"%s\" module that does not contain extension definitions.",
ext_p->name, mod->parsed->name),
LY_EVALID);
@@ -916,7 +952,7 @@
break;
}
}
- LY_CHECK_ERR_RET(!edef, LOGVAL(ctx->mod->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
+ LY_CHECK_ERR_RET(!edef, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
"Extension definition of extension instance \"%s\" not found.", ext_p->name),
LY_EVALID);
/* TODO plugins */
@@ -956,7 +992,7 @@
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(ctx->mod->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
"Invalid value \"%s\" of if-feature - unexpected end of expression.", *value);
return LY_EVALID;
} else if (!isspace(c[i + r])) {
@@ -993,25 +1029,25 @@
}
if (j || f_exp != f_size) {
/* not matching count of ( and ) */
- LOGVAL(ctx->mod->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
"Invalid value \"%s\" of if-feature - non-matching opening and closing parentheses.", *value);
return LY_EVALID;
}
if (checkversion || expr_size > 1) {
/* check that we have 1.1 module */
- if (ctx->mod->version != LYS_VERSION_1_1) {
- LOGVAL(ctx->mod->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
+ if (ctx->mod->compiled->version != LYS_VERSION_1_1) {
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
"Invalid value \"%s\" of if-feature - YANG 1.1 expression in YANG 1.0 module.", *value);
return LY_EVALID;
}
}
/* allocate the memory */
- LY_ARRAY_CREATE_RET(ctx->mod->ctx, iff->features, f_size, LY_EMEM);
+ LY_ARRAY_CREATE_RET(ctx->ctx, iff->features, f_size, LY_EMEM);
iff->expr = calloc((j = (expr_size / 4) + ((expr_size % 4) ? 1 : 0)), sizeof *iff->expr);
stack.stack = malloc(expr_size * sizeof *stack.stack);
- LY_CHECK_ERR_GOTO(!stack.stack || !iff->expr, LOGMEM(ctx->mod->ctx), error);
+ LY_CHECK_ERR_GOTO(!stack.stack || !iff->expr, LOGMEM(ctx->ctx), error);
stack.size = expr_size;
f_size--; expr_size--; /* used as indexes from now */
@@ -1068,9 +1104,9 @@
iff_setop(iff->expr, LYS_IFF_F, expr_size--);
/* now get the link to the feature definition */
- f = lysc_feature_find(ctx->mod, &c[i], j - i);
+ f = lysc_feature_find(ctx->mod->compiled, &c[i], j - i);
LY_CHECK_ERR_GOTO(!f,
- LOGVAL(ctx->mod->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
"Invalid value \"%s\" of if-feature - unable to find feature \"%.*s\".", *value, j - i, &c[i]);
rc = LY_EVALID,
error)
@@ -1086,7 +1122,7 @@
if (++expr_size || ++f_size) {
/* not all expected operators and operands found */
- LOGVAL(ctx->mod->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
"Invalid value \"%s\" of if-feature - processing error.", *value);
rc = LY_EINT;
} else {
@@ -1113,7 +1149,7 @@
imp->prefix = imp_p->prefix;
} else {
/* keep refcounts correct for lysp_module_free() */
- imp->prefix = lydict_insert(ctx->mod->ctx, imp_p->prefix, 0);
+ imp->prefix = lydict_insert(ctx->ctx, imp_p->prefix, 0);
}
COMPILE_ARRAY_GOTO(ctx, imp_p->exts, imp->exts, options, u, lys_compile_ext, ret, done);
imp->module = imp_p->module;
@@ -1124,18 +1160,18 @@
comp = imp->module->compiled;
/* try to get filepath from the compiled version */
if (comp->filepath) {
- mod = (struct lys_module*)lys_parse_path(ctx->mod->ctx, comp->filepath,
+ mod = (struct lys_module*)lys_parse_path(ctx->ctx, comp->filepath,
!strcmp(&comp->filepath[strlen(comp->filepath - 4)], ".yin") ? LYS_IN_YIN : LYS_IN_YANG);
if (mod != imp->module) {
- LOGERR(ctx->mod->ctx, LY_EINT, "Filepath \"%s\" of the module \"%s\" does not match.",
+ LOGERR(ctx->ctx, LY_EINT, "Filepath \"%s\" of the module \"%s\" does not match.",
comp->filepath, comp->name);
mod = NULL;
}
}
if (!mod) {
- if (lysp_load_module(ctx->mod->ctx, comp->name, comp->revision, 0, 1, &mod)) {
- LOGERR(ctx->mod->ctx, LY_ENOTFOUND, "Unable to reload \"%s\" module to import it into \"%s\", source data not found.",
- comp->name, ctx->mod->name);
+ if (lysp_load_module(ctx->ctx, comp->name, comp->revision, 0, 1, &mod)) {
+ LOGERR(ctx->ctx, LY_ENOTFOUND, "Unable to reload \"%s\" module to import it into \"%s\", source data not found.",
+ comp->name, ctx->mod->compiled->name);
return LY_ENOTFOUND;
}
}
@@ -1158,7 +1194,7 @@
ident->name = ident_p->name;
} else {
/* keep refcounts correct for lysp_module_free() */
- ident->name = lydict_insert(ctx->mod->ctx, ident_p->name, 0);
+ ident->name = lydict_insert(ctx->ctx, ident_p->name, 0);
}
COMPILE_ARRAY_GOTO(ctx, ident_p->iffeatures, ident->iffeatures, options, u, lys_compile_iffeature, ret, done);
/* backlings (derived) can be added no sooner than when all the identities in the current module are present */
@@ -1186,25 +1222,25 @@
if (s) {
/* prefixed identity */
name = &s[1];
- mod = lysc_module_find_prefix(ctx->mod, idents_p[i].bases[u], s - idents_p[i].bases[u])->compiled;
+ mod = lysc_module_find_prefix(ctx->mod->compiled, idents_p[i].bases[u], s - idents_p[i].bases[u])->compiled;
} else {
name = idents_p[i].bases[u];
- mod = ctx->mod;
+ mod = ctx->mod->compiled;
}
- LY_CHECK_ERR_RET(!mod, LOGVAL(ctx->mod->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
+ LY_CHECK_ERR_RET(!mod, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
"Invalid prefix used for base (%s) of identity \"%s\".", idents_p[i].bases[u], idents[i].name),
LY_EVALID);
if (mod->identities) {
for (v = 0; v < LY_ARRAY_SIZE(mod->identities); ++v) {
if (!strcmp(name, mod->identities[v].name)) {
/* we have match! store the backlink */
- LY_ARRAY_NEW_RET(ctx->mod->ctx, mod->identities[v].derived, dident, LY_EMEM);
+ LY_ARRAY_NEW_RET(ctx->ctx, mod->identities[v].derived, dident, LY_EMEM);
*dident = &idents[i];
break;
}
}
}
- LY_CHECK_ERR_RET(!dident, LOGVAL(ctx->mod->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
+ LY_CHECK_ERR_RET(!dident, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
"Unable to find base (%s) of identity \"%s\".", idents_p[i].bases[u], idents[i].name),
LY_EVALID);
}
@@ -1224,7 +1260,7 @@
feature->name = feature_p->name;
} else {
/* keep refcounts correct for lysp_module_free() */
- feature->name = lydict_insert(ctx->mod->ctx, feature_p->name, 0);
+ feature->name = lydict_insert(ctx->ctx, feature_p->name, 0);
}
feature->flags = feature_p->flags;
@@ -1235,7 +1271,7 @@
if (feature->iffeatures[u].features) {
for (v = 0; v < LY_ARRAY_SIZE(feature->iffeatures[u].features); ++v) {
/* add itself into the dependants list */
- LY_ARRAY_NEW_RET(ctx->mod->ctx, feature->iffeatures[u].features[v]->depfeatures, df, LY_EMEM);
+ LY_ARRAY_NEW_RET(ctx->ctx, feature->iffeatures[u].features[v]->depfeatures, df, LY_EMEM);
*df = feature;
}
/* TODO check for circular dependency */
@@ -1246,12 +1282,153 @@
return ret;
}
+static LY_ERR lys_compile_node(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *parent);
+
+static LY_ERR
+lys_compile_node_container(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *node)
+{
+ struct lysp_node_container *cont_p = (struct lysp_node_container*)node_p;
+ //struct lysc_node_container *cont = (struct lysc_node_container*)node;
+ struct lysp_node *child_p;
+
+ LY_LIST_FOR(cont_p->child, child_p) {
+ LY_CHECK_RET(lys_compile_node(ctx, child_p, options, node));
+ }
+
+ return LY_SUCCESS;
+}
+
+static LY_ERR
+lys_compile_node(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *parent)
+{
+ LY_ERR ret = LY_EVALID;
+ struct lysc_node *node;
+ unsigned int u;
+ LY_ERR (*node_compile_spec)(struct lysc_ctx*, struct lysp_node*, int, struct lysc_node*);
+
+ switch (node_p->nodetype) {
+ case LYS_CONTAINER:
+ node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_container));
+ node_compile_spec = lys_compile_node_container;
+ break;
+ case LYS_LEAF:
+ node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_leaf));
+ break;
+ case LYS_LIST:
+ node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_list));
+ break;
+ case LYS_LEAFLIST:
+ node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_leaflist));
+ break;
+ case LYS_CASE:
+ node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_case));
+ break;
+ case LYS_CHOICE:
+ node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_choice));
+ break;
+ case LYS_USES:
+ node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_uses));
+ break;
+ case LYS_ANYXML:
+ case LYS_ANYDATA:
+ node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_anydata));
+ break;
+ default:
+ LOGINT(ctx->ctx);
+ return LY_EINT;
+ }
+ LY_CHECK_ERR_RET(!node, LOGMEM(ctx->ctx), LY_EMEM);
+ node->nodetype = node_p->nodetype;
+ node->module = ctx->mod;
+ node->prev = node;
+ node->flags = node_p->flags;
+
+ /* config */
+ if (!(node->flags & LYS_CONFIG_MASK)) {
+ /* config not explicitely set, inherit it from parent */
+ if (parent) {
+ node->flags |= parent->flags & LYS_CONFIG_MASK;
+ } else {
+ /* default is config true */
+ node->flags |= LYS_CONFIG_W;
+ }
+ }
+
+ /* status - it is not inherited by specification, but it does not make sense to have
+ * current in deprecated or deprecated in obsolete, so we do print warning and inherit status */
+ if (!(node->flags & LYS_STATUS_MASK)) {
+ if (parent && (parent->flags & (LYS_STATUS_DEPRC | LYS_STATUS_OBSLT))) {
+ LOGWRN(ctx->ctx, "Missing explicit \"%s\" status in already specified in parent, inheriting.",
+ (parent->flags & LYS_STATUS_DEPRC) ? "deprecated" : "obsolete");
+ node->flags |= parent->flags & LYS_STATUS_MASK;
+ } else {
+ node->flags |= LYS_STATUS_CURR;
+ }
+ } else if (parent) {
+ /* check status compatibility with the parent */
+ if ((parent->flags & LYS_STATUS_MASK) > (node->flags & LYS_STATUS_MASK)) {
+ if (node->flags & LYS_STATUS_CURR) {
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
+ "A \"current\" status is in conflict with the parent's \"%s\" status.",
+ (parent->flags & LYS_STATUS_DEPRC) ? "deprecated" : "obsolete");
+ } else { /* LYS_STATUS_DEPRC */
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
+ "A \"deprecated\" status is in conflict with the parent's \"obsolete\" status.");
+ }
+ goto error;
+ }
+ }
+
+ if (options & LYSC_OPT_FREE_SP) {
+ /* just switch the pointers */
+ node->name = node_p->name;
+ } else {
+ node->sp = node_p;
+ /* keep refcounts correct for lysp_module_free() */
+ node->name = lydict_insert(ctx->ctx, node_p->name, 0);
+ }
+ COMPILE_ARRAY_GOTO(ctx, node_p->exts, node->exts, options, u, lys_compile_ext, ret, error);
+
+ /* nodetype-specific part */
+ LY_CHECK_GOTO(node_compile_spec(ctx, node_p, options, node), error);
+
+ /* insert into parent's children */
+ if (parent) {
+ if (!((struct lysc_node_case*)parent)->child) {
+ /* first child */
+ ((struct lysc_node_case*)parent)->child = node;
+ } else {
+ /* insert at the end of the parent's children list */
+ ((struct lysc_node_case*)parent)->child->prev->next = node;
+ node->prev = ((struct lysc_node_case*)parent)->child->prev;
+ ((struct lysc_node_case*)parent)->child->prev = node;
+ }
+ } else {
+ /* top-level element */
+ if (!ctx->mod->compiled->data) {
+ ctx->mod->compiled->data = node;
+ } else {
+ /* insert at the end of the module's top-level nodes list */
+ ctx->mod->compiled->data->prev->next = node;
+ node->prev = ctx->mod->compiled->data->prev;
+ ctx->mod->compiled->data->prev = node;
+ }
+ }
+
+ return LY_SUCCESS;
+
+error:
+ lysc_node_free(ctx->ctx, node, (options & LYSC_OPT_FREE_SP) ? 0 : 1);
+ return ret;
+}
+
LY_ERR
lys_compile(struct lys_module *mod, int options)
{
struct lysc_ctx ctx = {0};
struct lysc_module *mod_c;
struct lysp_module *sp;
+ struct lysp_node *node_p;
unsigned int u;
LY_ERR ret;
@@ -1263,7 +1440,10 @@
return LY_EINVAL;
}
- ctx.mod = ((struct lys_module*)mod)->compiled = mod_c = calloc(1, sizeof *mod_c);
+ ctx.ctx = sp->ctx;
+ ctx.mod = mod;
+
+ mod->compiled = mod_c = calloc(1, sizeof *mod_c);
LY_CHECK_ERR_RET(!mod_c, LOGMEM(sp->ctx), LY_EMEM);
mod_c->ctx = sp->ctx;
mod_c->implemented = sp->implemented;
@@ -1293,6 +1473,11 @@
COMPILE_ARRAY_GOTO(&ctx, sp->exts, mod_c->exts, options, u, lys_compile_ext, ret, error);
+ LY_LIST_FOR(sp->data, node_p) {
+ ret = lys_compile_node(&ctx, node_p, options, NULL);
+ LY_CHECK_GOTO(ret, error);
+ }
+
if (options & LYSC_OPT_FREE_SP) {
lysp_module_free_(mod->parsed, 0);
((struct lys_module*)mod)->parsed = NULL;
diff --git a/src/tree_schema.h b/src/tree_schema.h
index dfa04ce..b2c83cf 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -788,6 +788,14 @@
};
/**
+ * @brief Compiled YANG if-feature-stmt
+ */
+struct lysc_iffeature {
+ uint8_t *expr; /**< 2bits array describing the if-feature expression in prefix format, see @ref ifftokens */
+ struct lysc_feature **features; /**< array of pointers to the features used in expression ([sized array](@ref sizedarrays)) */
+};
+
+/**
* @brief YANG import-stmt
*/
struct lysc_import {
@@ -849,12 +857,6 @@
struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
};
-/**
- * @brief Compiled YANG if-feature-stmt
- */
-struct lysc_iffeature {
- uint8_t *expr; /**< 2bits array describing the if-feature expression in prefix format, see @ref ifftokens */
- struct lysc_feature **features; /**< array of pointers to the features used in expression ([sized array](@ref sizedarrays)) */
};
/**
@@ -863,14 +865,151 @@
struct lysc_node {
uint16_t nodetype; /**< type of the node (mandatory) */
uint16_t flags; /**< [schema node flags](@ref snodeflags) */
- struct lysp_node *sp; /**< link to the simply parsed (SP) original of the node, NULL if the SP schema was removed. */
- struct lysc_node *next; /**< pointer to the next sibling node (NULL if there is no one) */
+ struct lys_module *module; /**< module structure */
+ struct lysp_node *sp; /**< simply parsed (SP) original of the node, NULL if the SP schema was removed or in case of implicit case node. */
+ struct lysc_node *parent; /**< parent node (NULL in case of top level node) */
+ struct lysc_node *next; /**< next sibling node (NULL if there is no one) */
+ struct lysc_node *prev; /**< pointer to the previous sibling node \note Note that this pointer is
+ never NULL. If there is no sibling node, pointer points to the node
+ itself. In case of the first node, this pointer points to the last
+ node in the list. */
const char *name; /**< node name (mandatory) */
- struct lysc_when *when; /**< when statement */
- struct lysc_iffeature *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
};
+struct lysc_node_container {
+ uint16_t nodetype; /**< LYS_CONTAINER */
+ uint16_t flags; /**< [schema node flags](@ref snodeflags) */
+ struct lys_module *module; /**< module structure */
+ struct lysp_node *sp; /**< simply parsed (SP) original of the node, NULL if the SP schema was removed or in case of implicit case node. */
+ struct lysc_node *parent; /**< parent node (NULL in case of top level node) */
+ struct lysc_node *next; /**< next sibling node (NULL if there is no one) */
+ struct lysc_node *prev; /**< pointer to the previous sibling node \note Note that this pointer is
+ never NULL. If there is no sibling node, pointer points to the node
+ itself. In case of the first node, this pointer points to the last
+ node in the list. */
+ const char *name; /**< node name (mandatory) */
+ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+
+ struct lysc_node *child;
+};
+
+struct lysc_node_choice {
+ uint16_t nodetype; /**< LYS_CHOICE */
+ uint16_t flags; /**< [schema node flags](@ref snodeflags) */
+ struct lys_module *module; /**< module structure */
+ struct lysp_node *sp; /**< simply parsed (SP) original of the node, NULL if the SP schema was removed or in case of implicit case node. */
+ struct lysc_node *parent; /**< parent node (NULL in case of top level node) */
+ struct lysc_node *next; /**< next sibling node (NULL if there is no one) */
+ struct lysc_node *prev; /**< pointer to the previous sibling node \note Note that this pointer is
+ never NULL. If there is no sibling node, pointer points to the node
+ itself. In case of the first node, this pointer points to the last
+ node in the list. */
+ const char *name; /**< node name (mandatory) */
+ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+
+ struct lysc_node *child;
+};
+
+struct lysc_node_leaf {
+ uint16_t nodetype; /**< LYS_LEAF */
+ uint16_t flags; /**< [schema node flags](@ref snodeflags) */
+ struct lys_module *module; /**< module structure */
+ struct lysp_node *sp; /**< simply parsed (SP) original of the node, NULL if the SP schema was removed or in case of implicit case node. */
+ struct lysc_node *parent; /**< parent node (NULL in case of top level node) */
+ struct lysc_node *next; /**< next sibling node (NULL if there is no one) */
+ struct lysc_node *prev; /**< pointer to the previous sibling node \note Note that this pointer is
+ never NULL. If there is no sibling node, pointer points to the node
+ itself. In case of the first node, this pointer points to the last
+ node in the list. */
+ const char *name; /**< node name (mandatory) */
+ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+
+};
+
+struct lysc_node_leaflist {
+ uint16_t nodetype; /**< LYS_LEAFLIST */
+ uint16_t flags; /**< [schema node flags](@ref snodeflags) */
+ struct lys_module *module; /**< module structure */
+ struct lysp_node *sp; /**< simply parsed (SP) original of the node, NULL if the SP schema was removed or in case of implicit case node. */
+ struct lysc_node *parent; /**< parent node (NULL in case of top level node) */
+ struct lysc_node *next; /**< next sibling node (NULL if there is no one) */
+ struct lysc_node *prev; /**< pointer to the previous sibling node \note Note that this pointer is
+ never NULL. If there is no sibling node, pointer points to the node
+ itself. In case of the first node, this pointer points to the last
+ node in the list. */
+ const char *name; /**< node name (mandatory) */
+ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+
+};
+
+struct lysc_node_list {
+ uint16_t nodetype; /**< LYS_LIST */
+ uint16_t flags; /**< [schema node flags](@ref snodeflags) */
+ struct lys_module *module; /**< module structure */
+ struct lysp_node *sp; /**< simply parsed (SP) original of the node, NULL if the SP schema was removed or in case of implicit case node. */
+ struct lysc_node *parent; /**< parent node (NULL in case of top level node) */
+ struct lysc_node *next; /**< next sibling node (NULL if there is no one) */
+ struct lysc_node *prev; /**< pointer to the previous sibling node \note Note that this pointer is
+ never NULL. If there is no sibling node, pointer points to the node
+ itself. In case of the first node, this pointer points to the last
+ node in the list. */
+ const char *name; /**< node name (mandatory) */
+ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+
+ struct lysc_node *child;
+};
+
+struct lysc_node_anydata {
+ uint16_t nodetype; /**< LYS_ANYXML or LYS_ANYDATA */
+ uint16_t flags; /**< [schema node flags](@ref snodeflags) */
+ struct lys_module *module; /**< module structure */
+ struct lysp_node *sp; /**< simply parsed (SP) original of the node, NULL if the SP schema was removed or in case of implicit case node. */
+ struct lysc_node *parent; /**< parent node (NULL in case of top level node) */
+ struct lysc_node *next; /**< next sibling node (NULL if there is no one) */
+ struct lysc_node *prev; /**< pointer to the previous sibling node \note Note that this pointer is
+ never NULL. If there is no sibling node, pointer points to the node
+ itself. In case of the first node, this pointer points to the last
+ node in the list. */
+ const char *name; /**< node name (mandatory) */
+ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+
+};
+
+struct lysc_node_case {
+ uint16_t nodetype; /**< LYS_CASE */
+ uint16_t flags; /**< [schema node flags](@ref snodeflags) */
+ struct lys_module *module; /**< module structure */
+ struct lysp_node *sp; /**< simply parsed (SP) original of the node, NULL if the SP schema was removed or in case of implicit case node. */
+ struct lysc_node *parent; /**< parent node (NULL in case of top level node) */
+ struct lysc_node *next; /**< next sibling node (NULL if there is no one) */
+ struct lysc_node *prev; /**< pointer to the previous sibling node \note Note that this pointer is
+ never NULL. If there is no sibling node, pointer points to the node
+ itself. In case of the first node, this pointer points to the last
+ node in the list. */
+ const char *name; /**< node name (mandatory) */
+ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+
+ struct lysc_node *child;
+};
+
+struct lysc_node_uses {
+ uint16_t nodetype; /**< LYS_CHOICE */
+ uint16_t flags; /**< [schema node flags](@ref snodeflags) */
+ struct lys_module *module; /**< module structure */
+ struct lysp_node *sp; /**< simply parsed (SP) original of the node, NULL if the SP schema was removed or in case of implicit case node. */
+ struct lysc_node *parent; /**< parent node (NULL in case of top level node) */
+ struct lysc_node *next; /**< next sibling node (NULL if there is no one) */
+ struct lysc_node *prev; /**< pointer to the previous sibling node \note Note that this pointer is
+ never NULL. If there is no sibling node, pointer points to the node
+ itself. In case of the first node, this pointer points to the last
+ node in the list. */
+ const char *name; /**< node name (mandatory) */
+ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+
+ struct lysc_node *child;
+};
+
/**
* @brief Compiled YANG schema tree structure representing YANG module.
*
diff --git a/tests/src/test_tree_schema_compile.c b/tests/src/test_tree_schema_compile.c
index 91487ea..325b084 100644
--- a/tests/src/test_tree_schema_compile.c
+++ b/tests/src/test_tree_schema_compile.c
@@ -314,12 +314,45 @@
ly_ctx_destroy(ctx, NULL);
}
+static void
+test_node_container(void **state)
+{
+ (void) state; /* unused */
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+ struct lysc_node_container *cont;
+
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+ assert_non_null(mod = lys_parse_mem(ctx, "module a {namespace urn:a;prefix a;container c;}", LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+ assert_non_null(mod->compiled);
+ assert_non_null((cont = (struct lysc_node_container*)mod->compiled->data));
+ assert_int_equal(LYS_CONTAINER, cont->nodetype);
+ assert_string_equal("c", cont->name);
+ assert_true(cont->flags & LYS_CONFIG_W);
+ assert_true(cont->flags & LYS_STATUS_CURR);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;container c {config false;container child;}}", LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+ assert_non_null(mod->compiled);
+ assert_non_null((cont = (struct lysc_node_container*)mod->compiled->data));
+ assert_true(cont->flags & LYS_CONFIG_R);
+ assert_non_null((cont = (struct lysc_node_container*)cont->child));
+ assert_int_equal(LYS_CONTAINER, cont->nodetype);
+ assert_true(cont->flags & LYS_CONFIG_R);
+ assert_string_equal("child", cont->name);
+
+ ly_ctx_destroy(ctx, NULL);
+}
+
int main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test_setup(test_module, logger_setup),
cmocka_unit_test_setup(test_feature, logger_setup),
cmocka_unit_test_setup(test_identity, logger_setup),
+ cmocka_unit_test_setup(test_node_container, logger_setup),
};
return cmocka_run_group_tests(tests, NULL, NULL);