schema compile CHANGE better handling of features
- allow forward reference in feature's if-feature statements
- handling features of not implemented modules - all such features
are permanently disabled, but the structures must be available for
the implemented (compiled) modules which import their module.
diff --git a/src/context.c b/src/context.c
index d95b7b6..ad3abb2 100644
--- a/src/context.c
+++ b/src/context.c
@@ -289,10 +289,10 @@
* module in the context.
* @return Module matching the given key, NULL if no such module found.
*/
-static const struct lys_module *
+static struct lys_module *
ly_ctx_get_module_by_iter(const struct ly_ctx *ctx, const char *key, size_t key_offset, unsigned int *index)
{
- const struct lys_module *mod;
+ struct lys_module *mod;
const char *value;
for (; *index < ctx->list.count; ++(*index)) {
@@ -317,21 +317,20 @@
* revision module, use ly_ctx_get_module_latest_by().
* @return Matching module if any.
*/
-static const struct lys_module *
+static struct lys_module *
ly_ctx_get_module_by(const struct ly_ctx *ctx, const char *key, size_t key_offset, const char *revision)
{
- const struct lys_module *mod;
+ struct lys_module *mod;
unsigned int index = 0;
while ((mod = ly_ctx_get_module_by_iter(ctx, key, key_offset, &index))) {
if (!revision) {
- if ((mod->compiled && !mod->compiled->revision) || (!mod->compiled && !mod->parsed->revs)) {
+ if (!mod->revision) {
/* found requested module without revision */
return mod;
}
} else {
- if ((mod->compiled && mod->compiled->revision && !strcmp(mod->compiled->revision, revision)) ||
- (!mod->compiled && mod->parsed->revs && !strcmp(mod->parsed->revs[0].date, revision))) {
+ if (mod->revision && !strcmp(mod->revision, revision)) {
/* found requested module of the specific revision */
return mod;
}
@@ -341,14 +340,14 @@
return NULL;
}
-API const struct lys_module *
+API struct lys_module *
ly_ctx_get_module_ns(const struct ly_ctx *ctx, const char *ns, const char *revision)
{
LY_CHECK_ARG_RET(ctx, ctx, ns, NULL);
return ly_ctx_get_module_by(ctx, ns, offsetof(struct lys_module, ns), revision);
}
-API const struct lys_module *
+API struct lys_module *
ly_ctx_get_module(const struct ly_ctx *ctx, const char *name, const char *revision)
{
LY_CHECK_ARG_RET(ctx, ctx, name, NULL);
@@ -362,10 +361,10 @@
* @param[in] key_offset Key's offset in struct lys_module to get value from the context's modules to match with the key.
* @return Matching module if any.
*/
-static const struct lys_module *
+static struct lys_module *
ly_ctx_get_module_latest_by(const struct ly_ctx *ctx, const char *key, size_t key_offset)
{
- const struct lys_module *mod;
+ struct lys_module *mod;
unsigned int index = 0;
while ((mod = ly_ctx_get_module_by_iter(ctx, key, key_offset, &index))) {
@@ -377,14 +376,14 @@
return NULL;
}
-API const struct lys_module *
+API struct lys_module *
ly_ctx_get_module_latest(const struct ly_ctx *ctx, const char *name)
{
LY_CHECK_ARG_RET(ctx, ctx, name, NULL);
return ly_ctx_get_module_latest_by(ctx, name, offsetof(struct lys_module, name));
}
-const struct lys_module *
+API struct lys_module *
ly_ctx_get_module_latest_ns(const struct ly_ctx *ctx, const char *ns)
{
LY_CHECK_ARG_RET(ctx, ctx, ns, NULL);
@@ -398,10 +397,10 @@
* @param[in] key_offset Key's offset in struct lys_module to get value from the context's modules to match with the key.
* @return Matching module if any.
*/
-static const struct lys_module *
+static struct lys_module *
ly_ctx_get_module_implemented_by(const struct ly_ctx *ctx, const char *key, size_t key_offset)
{
- const struct lys_module *mod;
+ struct lys_module *mod;
unsigned int index = 0;
while ((mod = ly_ctx_get_module_by_iter(ctx, key, key_offset, &index))) {
@@ -413,14 +412,14 @@
return NULL;
}
-API const struct lys_module *
+API struct lys_module *
ly_ctx_get_module_implemented(const struct ly_ctx *ctx, const char *name)
{
LY_CHECK_ARG_RET(ctx, ctx, name, NULL);
return ly_ctx_get_module_implemented_by(ctx, name, offsetof(struct lys_module, name));
}
-API const struct lys_module *
+API struct lys_module *
ly_ctx_get_module_implemented_ns(const struct ly_ctx *ctx, const char *ns)
{
LY_CHECK_ARG_RET(ctx, ctx, ns, NULL);
@@ -485,6 +484,40 @@
}
}
+API LY_ERR
+ly_ctx_module_implement(struct ly_ctx *ctx, struct lys_module *mod)
+{
+ struct lys_module *m;
+
+ LY_CHECK_ARG_RET(ctx, mod, LY_EINVAL);
+
+ if (mod->implemented) {
+ return LY_SUCCESS;
+ }
+
+ /* we have module from the current context */
+ m = ly_ctx_get_module_implemented(ctx, mod->name);
+ if (m) {
+ if (m != mod) {
+ /* check collision with other implemented revision */
+ LOGERR(ctx, LY_EDENIED, "Module \"%s\" is present in the context in other implemented revision (%s).",
+ mod->name, mod->revision ? mod->revision : "module without revision");
+ return LY_EDENIED;
+ } else {
+ /* mod is already implemented */
+ return LY_SUCCESS;
+ }
+ }
+
+ /* mark the module implemented, check for collision was already done */
+ mod->implemented = 1;
+
+ /* compile the schema */
+ LY_CHECK_RET(lys_compile(mod, 0));
+
+ return LY_SUCCESS;
+}
+
API void
ly_ctx_destroy(struct ly_ctx *ctx, void (*private_destructor)(const struct lysc_node *node, void *priv))
{