schema tree CHANGE base for compiling extension instances
Just a generic part, does not work with extension plugins yet.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d06d2e6..0747637 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -180,6 +180,7 @@
src/libyang.h
src/context.h
src/tree_schema.h
+ src/extensions.h
src/dict.h
src/log.h
src/set.h)
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 8c117f1..42067d8 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -36,9 +36,9 @@
#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)->mod->ctx, ARRAY_C, LY_ARRAY_SIZE(ARRAY_P), RET, GOTO); \
for (ITER = 0; ITER < LY_ARRAY_SIZE(ARRAY_P); ++ITER) { \
- RET = FUNC(&(CTX), &(ARRAY_P)[ITER], OPTIONS, &(ARRAY_C)[ITER]); \
+ RET = FUNC(CTX, &(ARRAY_P)[ITER], OPTIONS, &(ARRAY_C)[ITER]); \
LY_CHECK_GOTO(RET != LY_SUCCESS, GOTO); \
LY_ARRAY_INCREMENT(ARRAY_C); \
} \
@@ -596,7 +596,7 @@
for (i = 0; i < len; ++i) {
if (name[i] == ':') {
/* we have a prefixed feature */
- mod = lysc_module_find_prefix(mod, name, i);
+ mod = lysc_module_find_prefix(mod, name, i)->compiled;
LY_CHECK_RET(!mod, NULL);
name = &name[i + 1];
@@ -823,15 +823,63 @@
}
static LY_ERR
-lys_compile_iffeature(struct lysc_ctx *ctx, const char *value, int UNUSED(options), struct lysc_iffeature *iff, struct lysc_feature *parent)
+lys_compile_ext(struct lysc_ctx *ctx, struct lysp_ext_instance *ext_p, int options, struct lysc_ext_instance *ext)
{
- const char *c = value;
+ const char *name;
+ unsigned int u;
+ const struct lys_module *mod;
+ struct lysp_ext *edef;
+
+ if (options & LYSC_OPT_FREE_SP) {
+ /* just switch the pointers */
+ 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->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,
+ "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,
+ "Extension instance \"%s\" refers \"%s\" module that does not contain extension definitions.",
+ ext_p->name, mod->parsed->name),
+ LY_EVALID);
+ name = &ext_p->name[u + 1];
+ /* find the extension definition there */
+ for (ext = NULL, u = 0; u < LY_ARRAY_SIZE(mod->parsed->extensions); ++u) {
+ if (!strcmp(name, mod->parsed->extensions[u].name)) {
+ edef = &mod->parsed->extensions[u];
+ break;
+ }
+ }
+ LY_CHECK_ERR_RET(!edef, LOGVAL(ctx->mod->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
+ "Extension definition of extension instance \"%s\" not found.", ext_p->name),
+ LY_EVALID);
+ /* TODO plugins */
+
+ return LY_SUCCESS;
+}
+
+/**
+ * @param[in] parent Provided only in case the if-feature is inside
+ */
+static LY_ERR
+lys_compile_iffeature(struct lysc_ctx *ctx, const char **value, int UNUSED(options), struct lysc_iffeature *iff)
+{
+ const char *c = *value;
int r, rc = EXIT_FAILURE;
int i, j, last_not, checkversion = 0;
unsigned int f_size = 0, expr_size = 0, f_exp = 1;
uint8_t op;
struct iff_stack stack = {0, 0, NULL};
- struct lysc_feature *f, **df;
+ struct lysc_feature *f;
assert(c);
@@ -852,7 +900,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,
- "Invalid value \"%s\" of if-feature - unexpected end of expression.", value);
+ "Invalid value \"%s\" of if-feature - unexpected end of expression.", *value);
return LY_EVALID;
} else if (!isspace(c[i + r])) {
/* feature name starting with the not/and/or */
@@ -889,7 +937,7 @@
if (j || f_exp != f_size) {
/* not matching count of ( and ) */
LOGVAL(ctx->mod->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
- "Invalid value \"%s\" of if-feature - non-matching opening and closing parentheses.", value);
+ "Invalid value \"%s\" of if-feature - non-matching opening and closing parentheses.", *value);
return LY_EVALID;
}
@@ -897,7 +945,7 @@
/* 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,
- "Invalid value \"%s\" of if-feature - YANG 1.1 expression in YANG 1.0 module.", value);
+ "Invalid value \"%s\" of if-feature - YANG 1.1 expression in YANG 1.0 module.", *value);
return LY_EVALID;
}
}
@@ -966,18 +1014,11 @@
f = lysc_feature_find(ctx->mod, &c[i], j - i);
LY_CHECK_ERR_GOTO(!f,
LOGVAL(ctx->mod->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]);
+ "Invalid value \"%s\" of if-feature - unable to find feature \"%.*s\".", *value, j - i, &c[i]);
rc = LY_EINVAL,
error)
iff->features[f_size] = f;
LY_ARRAY_INCREMENT(iff->features);
- if (parent) {
- /* and add itself into the dependants list */
- LY_ARRAY_NEW_RET(ctx->mod->ctx, f->depfeatures, df, LY_EMEM);
- *df = parent;
-
- /* TODO check for circular dependency */
- }
f_size--;
}
}
@@ -989,7 +1030,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,
- "Invalid value \"%s\" of if-feature - processing error.", value);
+ "Invalid value \"%s\" of if-feature - processing error.", *value);
rc = LY_EINT;
} else {
rc = LY_SUCCESS;
@@ -1005,8 +1046,10 @@
static LY_ERR
lys_compile_import(struct lysc_ctx *ctx, struct lysp_import *imp_p, int options, struct lysc_import *imp)
{
+ unsigned int u;
struct lys_module *mod;
struct lysc_module *comp;
+ LY_ERR ret = LY_SUCCESS;
if (options & LYSC_OPT_FREE_SP) {
/* just switch the pointers */
@@ -1015,6 +1058,7 @@
/* keep refcounts correct for lysp_module_free() */
imp->prefix = lydict_insert(ctx->mod->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;
/* make sure that we have both versions (lysp_ and lysc_) of the imported module. To import groupings or
@@ -1042,14 +1086,16 @@
return lys_compile(imp->module->parsed, options, &imp->module->compiled);
}
- return LY_SUCCESS;
+done:
+ return ret;
}
static LY_ERR
lys_compile_feature(struct lysc_ctx *ctx, struct lysp_feature *feature_p, int options, struct lysc_feature *feature)
{
- unsigned int u;
- LY_ERR ret;
+ unsigned int u, v;
+ LY_ERR ret = LY_SUCCESS;
+ struct lysc_feature **df;
if (options & LYSC_OPT_FREE_SP) {
/* just switch the pointers */
@@ -1060,18 +1106,22 @@
}
feature->flags = feature_p->flags;
- if (feature_p->iffeatures) {
- /* allocate everything now */
- LY_ARRAY_CREATE_RET(ctx->mod->ctx, feature->iffeatures, LY_ARRAY_SIZE(feature_p->iffeatures), LY_EMEM);
-
- for (u = 0; u < LY_ARRAY_SIZE(feature_p->iffeatures); ++u) {
- ret = lys_compile_iffeature(ctx, feature_p->iffeatures[u], options, &feature->iffeatures[u], feature);
- LY_CHECK_RET(ret);
- LY_ARRAY_INCREMENT(feature->iffeatures);
+ COMPILE_ARRAY_GOTO(ctx, feature_p->exts, feature->exts, options, u, lys_compile_ext, ret, done);
+ COMPILE_ARRAY_GOTO(ctx, feature_p->iffeatures, feature->iffeatures, options, u, lys_compile_iffeature, ret, done);
+ if (feature->iffeatures) {
+ for (u = 0; u < LY_ARRAY_SIZE(feature->iffeatures); ++u) {
+ 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);
+ *df = feature;
+ }
+ /* TODO check for circular dependency */
+ }
}
}
-
- return LY_SUCCESS;
+done:
+ return ret;
}
LY_ERR
@@ -1106,8 +1156,10 @@
mod_c->prefix = lydict_insert(sp->ctx, sp->prefix, 0);
}
- COMPILE_ARRAY_GOTO(ctx, sp->imports, mod_c->imports, options, u, lys_compile_import, ret, error);
- COMPILE_ARRAY_GOTO(ctx, sp->features, mod_c->features, options, u, lys_compile_feature, ret, error);
+ COMPILE_ARRAY_GOTO(&ctx, sp->imports, mod_c->imports, options, u, lys_compile_import, ret, error);
+ COMPILE_ARRAY_GOTO(&ctx, sp->features, mod_c->features, options, u, lys_compile_feature, ret, error);
+
+ COMPILE_ARRAY_GOTO(&ctx, sp->exts, mod_c->exts, options, u, lys_compile_ext, ret, error);
if (options & LYSC_OPT_FREE_SP) {
lysp_module_free_(sp, 0);
diff --git a/src/tree_schema.h b/src/tree_schema.h
index ff1d929..5c634c3 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -17,6 +17,8 @@
#include <stdint.h>
+#include "extensions.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -208,56 +210,6 @@
};
/**
- * @brief Enum of substatements in which extension instances can appear.
- */
-typedef enum {
- LYEXT_SUBSTMT_SELF = 0, /**< extension of the structure itself, not substatement's */
- LYEXT_SUBSTMT_ARGUMENT, /**< extension of the argument statement, can appear in lys_ext */
- LYEXT_SUBSTMT_BASE, /**< extension of the base statement, can appear (repeatedly) in lys_type and lys_ident */
- LYEXT_SUBSTMT_BELONGSTO, /**< extension of the belongs-to statement, can appear in lys_submodule */
- LYEXT_SUBSTMT_CONTACT, /**< extension of the contact statement, can appear in lys_module */
- LYEXT_SUBSTMT_DEFAULT, /**< extension of the default statement, can appear in lys_node_leaf, lys_node_leaflist,
- lys_node_choice and lys_deviate */
- LYEXT_SUBSTMT_DESCRIPTION, /**< extension of the description statement, can appear in lys_module, lys_submodule,
- lys_node, lys_import, lys_include, lys_ext, lys_feature, lys_tpdf, lys_restr,
- lys_ident, lys_deviation, lys_type_enum, lys_type_bit, lys_when and lys_revision */
- LYEXT_SUBSTMT_ERRTAG, /**< extension of the error-app-tag statement, can appear in lys_restr */
- LYEXT_SUBSTMT_ERRMSG, /**< extension of the error-message statement, can appear in lys_restr */
- LYEXT_SUBSTMT_KEY, /**< extension of the key statement, can appear in lys_node_list */
- LYEXT_SUBSTMT_NAMESPACE, /**< extension of the namespace statement, can appear in lys_module */
- LYEXT_SUBSTMT_ORGANIZATION, /**< extension of the organization statement, can appear in lys_module and lys_submodule */
- LYEXT_SUBSTMT_PATH, /**< extension of the path statement, can appear in lys_type */
- LYEXT_SUBSTMT_PREFIX, /**< extension of the prefix statement, can appear in lys_module, lys_submodule (for
- belongs-to's prefix) and lys_import */
- LYEXT_SUBSTMT_PRESENCE, /**< extension of the presence statement, can appear in lys_node_container */
- LYEXT_SUBSTMT_REFERENCE, /**< extension of the reference statement, can appear in lys_module, lys_submodule,
- lys_node, lys_import, lys_include, lys_revision, lys_tpdf, lys_restr, lys_ident,
- lys_ext, lys_feature, lys_deviation, lys_type_enum, lys_type_bit and lys_when */
- LYEXT_SUBSTMT_REVISIONDATE, /**< extension of the revision-date statement, can appear in lys_import and lys_include */
- LYEXT_SUBSTMT_UNITS, /**< extension of the units statement, can appear in lys_tpdf, lys_node_leaf,
- lys_node_leaflist and lys_deviate */
- LYEXT_SUBSTMT_VALUE, /**< extension of the value statement, can appear in lys_type_enum */
- LYEXT_SUBSTMT_VERSION, /**< extension of the yang-version statement, can appear in lys_module and lys_submodule */
- LYEXT_SUBSTMT_MODIFIER, /**< extension of the modifier statement, can appear in lys_restr */
- LYEXT_SUBSTMT_REQINSTANCE, /**< extension of the require-instance statement, can appear in lys_type */
- LYEXT_SUBSTMT_YINELEM, /**< extension of the yin-element statement, can appear in lys_ext */
- LYEXT_SUBSTMT_CONFIG, /**< extension of the config statement, can appear in lys_node and lys_deviate */
- LYEXT_SUBSTMT_MANDATORY, /**< extension of the mandatory statement, can appear in lys_node_leaf, lys_node_choice,
- lys_node_anydata and lys_deviate */
- LYEXT_SUBSTMT_ORDEREDBY, /**< extension of the ordered-by statement, can appear in lys_node_list and lys_node_leaflist */
- LYEXT_SUBSTMT_STATUS, /**< extension of the status statement, can appear in lys_tpdf, lys_node, lys_ident,
- lys_ext, lys_feature, lys_type_enum and lys_type_bit */
- LYEXT_SUBSTMT_FRACDIGITS, /**< extension of the fraction-digits statement, can appear in lys_type */
- LYEXT_SUBSTMT_MAX, /**< extension of the max-elements statement, can appear in lys_node_list,
- lys_node_leaflist and lys_deviate */
- LYEXT_SUBSTMT_MIN, /**< extension of the min-elements statement, can appear in lys_node_list,
- lys_node_leaflist and lys_deviate */
- LYEXT_SUBSTMT_POSITION, /**< extension of the position statement, can appear in lys_type_bit */
- LYEXT_SUBSTMT_UNIQUE, /**< extension of the unique statement, can appear in lys_node_list and lys_deviate */
- LYEXT_SUBSTMT_IFFEATURE, /**< extension of the if-feature statement */
-} LYEXT_SUBSTMT;
-
-/**
* @brief YANG extension instance
*/
struct lysp_ext_instance {
@@ -790,12 +742,34 @@
void lysp_module_free(struct lysp_module *module);
/**
+ * @brief YANG extension instance
+ */
+struct lysc_ext_instance {
+ struct lyext_plugin *plugin; /**< pointer to the plugin implementing the extension (if present) */
+ void *parent; /**< pointer to the parent element holding the extension instance(s), use
+ ::lysc_ext_instance#parent_type to access the schema element */
+ const char *argument; /**< optional value of the extension's argument */
+ LYEXT_SUBSTMT insubstmt; /**< value identifying placement of the extension instance */
+ uint32_t insubstmt_index; /**< in case the instance is in a substatement that can appear multiple times,
+ this identifies the index of the substatement for this extension instance */
+#if 0
+ uint8_t parent_type; /**< #LYEXT_PAR - type of the parent structure */
+ uint8_t ext_type; /**< extension type (#LYEXT_TYPE) */
+ uint8_t padding; /**< 32b padding */
+ struct lys_ext_instance **ext; /**< array of pointers to the extension instances */
+ void *priv; /**< private caller's data, not used by libyang */
+ struct lys_module *module; /**< pointer to the extension instance's module (mandatory) */
+ LYS_NODE nodetype; /**< LYS_EXT */
+#endif
+};
+
+/**
* @brief YANG import-stmt
*/
struct lysc_import {
struct lys_module *module; /**< link to the imported module */
const char *prefix; /**< prefix for the data from the imported schema (mandatory) */
- struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
};
/**
@@ -813,7 +787,7 @@
const char *name; /**< feature name (mandatory) */
struct lysc_feature **depfeatures;/**< list of pointers to other features depending on this one ([sized array](@ref sizedarrays)) */
struct lysc_iffeature *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
- struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
uint16_t flags; /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* and
#LYS_FENABLED values allowed */
};
@@ -878,9 +852,9 @@
in the list is always the last (newest) revision of the module */
struct lysc_import *imports; /**< list of imported modules ([sized array](@ref sizedarrays)) */
-
struct lysc_feature *features; /**< list of feature definitions ([sized array](@ref sizedarrays)) */
+ struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
uint8_t implemented:1; /**< flag if the module is implemented, not just imported */
uint8_t latest_revision:1; /**< flag if the module was loaded without specific revision and is
diff --git a/src/tree_schema_helpers.c b/src/tree_schema_helpers.c
index e4d26b9..4675e63 100644
--- a/src/tree_schema_helpers.c
+++ b/src/tree_schema_helpers.c
@@ -280,30 +280,38 @@
return LY_SUCCESS;
}
-struct lysc_module *
+#define FIND_MODULE(TYPE, MOD) \
+ TYPE *imp; \
+ if (!strncmp((MOD)->prefix, prefix, len) && (MOD)->prefix[len] == '\0') { \
+ /* it is the prefix of the module itself */ \
+ return (struct lys_module*)ly_ctx_get_module((MOD)->ctx, (MOD)->name, (MOD)->revs ? (MOD)->revs[0].date : NULL); \
+ } \
+ /* search in imports */ \
+ LY_ARRAY_FOR((MOD)->imports, TYPE, imp) { \
+ if (!strncmp(imp->prefix, prefix, len) && (MOD)->prefix[len] == '\0') { \
+ return imp->module; \
+ } \
+ } \
+ return NULL
+
+struct lys_module *
lysc_module_find_prefix(struct lysc_module *mod, const char *prefix, size_t len)
{
- struct lysc_import *imp;
+ FIND_MODULE(struct lysc_import, mod);
+}
- assert(mod);
+struct lys_module *
+lysp_module_find_prefix(struct lysp_module *mod, const char *prefix, size_t len)
+{
+ FIND_MODULE(struct lysp_import, mod);
+}
- if (!strncmp(mod->prefix, prefix, len) && mod->prefix[len] == '\0') {
- /* it is the prefix of the module itself */
- return mod;
+struct lys_module *
+lys_module_find_prefix(struct lys_module *mod, const char *prefix, size_t len)
+{
+ if (mod->compiled) {
+ FIND_MODULE(struct lysc_import, mod->compiled);
+ } else {
+ FIND_MODULE(struct lysp_import, mod->parsed);
}
-
- /* search in imports */
- LY_ARRAY_FOR(mod->imports, struct lysc_import, imp) {
- if (!strncmp(imp->prefix, prefix, len) && mod->prefix[len] == '\0') {
- if (!imp->module->compiled) {
- /* shouldn't be needed, the function is internally used when
- * the imported modules should be also compiled. But for sure
- * and possible future optimizations, check it here */
- lys_compile(imp->module->parsed, 0, &imp->module->compiled);
- }
- return imp->module->compiled;
- }
- }
-
- return NULL;
}
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index f99d6f6..0c5c3ac 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -100,6 +100,26 @@
LY_ERR lysp_load_submodule(struct ly_ctx *ctx, struct lysp_module *mod, struct lysp_include *inc);
/**
+ * @brief Find the module referenced by prefix in the provided parsed mod.
+ *
+ * @param[in] mod Schema module where the prefix was used.
+ * @param[in] prefix Prefix used to reference a module.
+ * @param[in] len Length of the prefix since it is not necessary NULL-terminated.
+ * @return Pointer to the module or NULL if the module is not found.
+ */
+struct lys_module *lysp_module_find_prefix(struct lysp_module *mod, const char *prefix, size_t len);
+
+/**
+ * @brief Find the module referenced by prefix in the provided compiled mod.
+ *
+ * @param[in] mod Schema module where the prefix was used.
+ * @param[in] prefix Prefix used to reference a module.
+ * @param[in] len Length of the prefix since it is not necessary NULL-terminated.
+ * @return Pointer to the module or NULL if the module is not found.
+ */
+struct lys_module *lysc_module_find_prefix(struct lysc_module *mod, const char *prefix, size_t len);
+
+/**
* @brief Find the module referenced by prefix in the provided mod.
*
* @param[in] mod Schema module where the prefix was used.
@@ -107,7 +127,7 @@
* @param[in] len Length of the prefix since it is not necessary NULL-terminated.
* @return Pointer to the module or NULL if the module is not found.
*/
-struct lysc_module *lysc_module_find_prefix(struct lysc_module *mod, const char *prefix, size_t len);
+struct lys_module *lys_module_find_prefix(struct lys_module *mod, const char *prefix, size_t len);
/**
* @brief Parse YANG module and submodule from a string.