schema tree REFACTOR always parse and implement separately
diff --git a/src/context.c b/src/context.c
index ac62cac..a4a9049 100644
--- a/src/context.c
+++ b/src/context.c
@@ -194,7 +194,11 @@
LY_CHECK_ARG_RET(ctx, ctx, name, NULL);
- LY_CHECK_GOTO(ret = lys_load_module(ctx, name, revision, 1, features, &unres, &result), cleanup);
+ /* parse */
+ LY_CHECK_GOTO(ret = lys_parse_load(ctx, name, revision, &unres, &result), cleanup);
+
+ /* implement */
+ LY_CHECK_GOTO(ret = lys_implement(result, features, &unres), cleanup);
/* resolve unres and revert, if needed */
LY_CHECK_GOTO(ret = lys_compile_unres_glob(ctx, &unres), cleanup);
@@ -279,8 +283,10 @@
/* load internal modules */
for (i = 0; i < ((options & LY_CTX_NO_YANGLIBRARY) ? (LY_INTERNAL_MODS_COUNT - 2) : LY_INTERNAL_MODS_COUNT); i++) {
ly_in_memory(in, internal_modules[i].data);
- LY_CHECK_GOTO(rc = lys_create_module(ctx, in, internal_modules[i].format, internal_modules[i].implemented,
- NULL, NULL, NULL, &unres, &module), error);
+ LY_CHECK_GOTO(rc = lys_parse_in(ctx, in, internal_modules[i].format, NULL, NULL, &unres, &module), error);
+ if (internal_modules[i].implemented || (ctx->flags & LY_CTX_ALL_IMPLEMENTED)) {
+ LY_CHECK_GOTO(rc = lys_implement(module, NULL, &unres), error);
+ }
}
/* resolve global unres */
diff --git a/src/path.c b/src/path.c
index 4109f73..9500422 100644
--- a/src/path.c
+++ b/src/path.c
@@ -431,7 +431,7 @@
}
assert(unres);
- LY_CHECK_GOTO(ret = lys_set_implemented_r((struct lys_module *)*mod, NULL, unres), error);
+ LY_CHECK_GOTO(ret = lys_implement((struct lys_module *)*mod, NULL, unres), error);
if (unres->recompile) {
return LY_ERECOMPILE;
}
diff --git a/src/plugins_types.c b/src/plugins_types.c
index a2cf0f3..adfeb17 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -751,7 +751,7 @@
API LY_ERR
lyplg_type_make_implemented(struct lys_module *mod, const char **features, struct lys_glob_unres *unres)
{
- LY_CHECK_RET(lys_set_implemented_r(mod, features, unres));
+ LY_CHECK_RET(lys_implement(mod, features, unres));
if (unres->recompile) {
return LY_ERECOMPILE;
diff --git a/src/schema_compile.c b/src/schema_compile.c
index d7312da..11c317c 100644
--- a/src/schema_compile.c
+++ b/src/schema_compile.c
@@ -836,7 +836,7 @@
if (!mod->implemented) {
/* unimplemented module found */
if (implement) {
- LY_CHECK_RET(lys_set_implemented_r((struct lys_module *)mod, NULL, unres));
+ LY_CHECK_RET(lys_implement((struct lys_module *)mod, NULL, unres));
if (unres->recompile) {
return LY_ERECOMPILE;
}
diff --git a/src/schema_compile_amend.c b/src/schema_compile_amend.c
index 1ea084b..e571546 100644
--- a/src/schema_compile_amend.c
+++ b/src/schema_compile_amend.c
@@ -2272,7 +2272,7 @@
if (!mod->implemented) {
/* implement (compile) the target module with our augments/deviations */
- LY_CHECK_GOTO(ret = lys_set_implemented_r(mod, NULL, ctx->unres), cleanup);
+ LY_CHECK_GOTO(ret = lys_implement(mod, NULL, ctx->unres), cleanup);
} else if (!ctx->unres->full_compilation) {
/* target module was already compiled, we need to recompile it */
ctx->unres->recompile = 1;
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 4a57cc4..d2ed415 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -798,11 +798,15 @@
}
LY_ERR
-lys_set_implemented_r(struct lys_module *mod, const char **features, struct lys_glob_unres *unres)
+lys_implement(struct lys_module *mod, const char **features, struct lys_glob_unres *unres)
{
+ LY_ERR ret;
struct lys_module *m;
- assert(!mod->implemented);
+ if (mod->implemented) {
+ /* nothing to do */
+ return LY_SUCCESS;
+ }
/* we have module from the current context */
m = ly_ctx_get_module_implemented(mod->ctx, mod->name);
@@ -815,8 +819,11 @@
return LY_EDENIED;
}
- /* enable features */
- LY_CHECK_RET(lys_enable_features(mod->parsed, features));
+ /* set features */
+ ret = lys_set_features(mod->parsed, features);
+ if (ret && (ret != LY_EEXIST)) {
+ return ret;
+ }
if (mod->ctx->flags & LY_CTX_EXPLICIT_COMPILE) {
/* do not compile the module yet */
@@ -869,7 +876,7 @@
}
/* implement this module and any other required modules, recursively */
- ret = lys_set_implemented_r(mod, features, &unres);
+ ret = lys_implement(mod, features, &unres);
/* the first module being implemented is finished, resolve global unres, consolidate the set */
if (!ret) {
@@ -894,8 +901,10 @@
LY_ARRAY_FOR(pmod->imports, u) {
imp = &pmod->imports[u];
if (!imp->module) {
- LY_CHECK_RET(lys_load_module(PARSER_CTX(pctx), imp->name, imp->rev[0] ? imp->rev : NULL, 0, NULL,
- pctx->unres, &imp->module));
+ LY_CHECK_RET(lys_parse_load(PARSER_CTX(pctx), imp->name, imp->rev[0] ? imp->rev : NULL, pctx->unres, &imp->module));
+ if (PARSER_CTX(pctx)->flags & LY_CTX_ALL_IMPLEMENTED) {
+ LY_CHECK_RET(lys_implement(imp->module, NULL, pctx->unres));
+ }
}
/* check for importing the same module twice */
for (v = 0; v < u; ++v) {
@@ -1214,11 +1223,11 @@
}
LY_ERR
-lys_create_module(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, ly_bool need_implemented,
+lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format,
LY_ERR (*custom_check)(const struct ly_ctx *ctx, struct lysp_module *mod, struct lysp_submodule *submod, void *data),
- void *check_data, const char **features, struct lys_glob_unres *unres, struct lys_module **module)
+ void *check_data, struct lys_glob_unres *unres, struct lys_module **module)
{
- struct lys_module *mod = NULL, *latest, *mod_dup, *mod_impl;
+ struct lys_module *mod = NULL, *latest, *mod_dup;
struct lysp_submodule *submod;
LY_ERR ret;
LY_ARRAY_COUNT_TYPE u;
@@ -1227,20 +1236,13 @@
struct lys_parser_ctx *pctx = NULL;
char *filename, *rev, *dot;
size_t len;
- ly_bool implement;
- assert(ctx && in && (!features || need_implemented) && unres);
+ assert(ctx && in && unres);
if (module) {
*module = NULL;
}
- if (ctx->flags & LY_CTX_ALL_IMPLEMENTED) {
- implement = 1;
- } else {
- implement = need_implemented;
- }
-
mod = calloc(1, sizeof *mod);
LY_CHECK_ERR_RET(!mod, LOGMEM(ctx), LY_EMEM);
mod->ctx = ctx;
@@ -1295,29 +1297,7 @@
/* check whether it is not already in the context in the same revision */
mod_dup = (struct lys_module *)ly_ctx_get_module(ctx, mod->name, mod->revision);
- if (implement) {
- mod_impl = ly_ctx_get_module_implemented(ctx, mod->name);
- if (mod_impl && (mod_impl != mod_dup)) {
- LOGERR(ctx, LY_EDENIED, "Module \"%s@%s\" is already implemented in the context.", mod_impl->name,
- mod_impl->revision ? mod_impl->revision : "<none>");
- ret = LY_EDENIED;
- goto free_mod_cleanup;
- }
- }
if (mod_dup) {
- if (implement) {
- if (!mod_dup->implemented) {
- /* just implement it */
- LY_CHECK_GOTO(ret = lys_set_implemented_r(mod_dup, features, unres), free_mod_cleanup);
- goto free_mod_cleanup;
- }
-
- /* nothing to do */
- LOGVRB("Module \"%s@%s\" is already implemented in the context.", mod_dup->name,
- mod_dup->revision ? mod_dup->revision : "<none>");
- goto free_mod_cleanup;
- }
-
/* nothing to do */
LOGVRB("Module \"%s@%s\" is already present in the context.", mod_dup->name,
mod_dup->revision ? mod_dup->revision : "<none>");
@@ -1402,11 +1382,6 @@
LY_CHECK_GOTO(ret, cleanup);
}
- if (implement) {
- /* implement (compile) */
- LY_CHECK_GOTO(ret = lys_set_implemented_r(mod, features, unres), cleanup);
- }
-
/* success */
goto cleanup;
@@ -1463,6 +1438,7 @@
lys_parse(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, const char **features, const struct lys_module **module)
{
LY_ERR ret;
+ struct lys_module *mod;
struct lys_glob_unres unres = {0};
if (module) {
@@ -1476,7 +1452,12 @@
/* remember input position */
in->func_start = in->current;
- ret = lys_create_module(ctx, in, format, 1, NULL, NULL, features, &unres, (struct lys_module **)module);
+ /* parse */
+ ret = lys_parse_in(ctx, in, format, NULL, NULL, &unres, &mod);
+ LY_CHECK_GOTO(ret, cleanup);
+
+ /* implement */
+ ret = lys_implement(mod, features, &unres);
LY_CHECK_GOTO(ret, cleanup);
/* resolve global unres */
diff --git a/src/tree_schema_helpers.c b/src/tree_schema_helpers.c
index 14572ce..704095f 100644
--- a/src/tree_schema_helpers.c
+++ b/src/tree_schema_helpers.c
@@ -618,17 +618,13 @@
}
/**
- * @brief Load the (sub)module into the context.
+ * @brief Parse a (sub)module from a local file and add into the context.
*
* This function does not check the presence of the (sub)module in context, it should be done before calling this function.
*
- * module_name and submodule_name are alternatives - only one of the
- *
* @param[in] ctx libyang context where to work.
* @param[in] name Name of the (sub)module to load.
* @param[in] revision Optional revision of the (sub)module to load, if NULL the newest revision is being loaded.
- * @param[in] features Array of enabled features ended with NULL.
- * @param[in] need_implemented Whether the (sub)module is needed implemented or not.
* @param[in] main_ctx Parser context of the main module in case of loading submodule.
* @param[in] main_name Main module name in case of loading submodule.
* @param[in] required Module is required so error (even if the input file not found) are important. If 0, there is some
@@ -636,12 +632,13 @@
* @param[in,out] unres Global unres structure for newly implemented modules.
* @param[out] result Parsed YANG schema tree of the requested module (struct lys_module*) or submodule (struct lysp_submodule*).
* If it is a module, it is already in the context!
- * @return LY_ERR value, in case of LY_SUCCESS, the \arg result is always provided.
+ * @return LY_SUCCESS on success.
+ * @return LY_ERECOMPILE if unres->recompile dep set needs to be recompiled, @p result is set.
+ * @return LY_ERR on error.
*/
static LY_ERR
-lys_module_localfile(struct ly_ctx *ctx, const char *name, const char *revision, const char **features,
- ly_bool need_implemented, struct lys_parser_ctx *main_ctx, const char *main_name, ly_bool required,
- struct lys_glob_unres *unres, void **result)
+lys_parse_localfile(struct ly_ctx *ctx, const char *name, const char *revision, struct lys_parser_ctx *main_ctx,
+ const char *main_name, ly_bool required, struct lys_glob_unres *unres, void **result)
{
struct ly_in *in;
char *filepath = NULL;
@@ -673,8 +670,7 @@
ret = lys_parse_submodule(ctx, in, format, main_ctx, lysp_load_module_check, &check_data,
(struct lysp_submodule **)&mod);
} else {
- ret = lys_create_module(ctx, in, format, need_implemented, lysp_load_module_check, &check_data, features, unres,
- (struct lys_module **)&mod);
+ ret = lys_parse_in(ctx, in, format, lysp_load_module_check, &check_data, unres, (struct lys_module **)&mod);
}
ly_in_free(in, 1);
@@ -690,27 +686,19 @@
}
LY_ERR
-lys_load_module(struct ly_ctx *ctx, const char *name, const char *revision, ly_bool need_implemented,
- const char **features, struct lys_glob_unres *unres, struct lys_module **mod)
+lys_parse_load(struct ly_ctx *ctx, const char *name, const char *revision, struct lys_glob_unres *unres,
+ struct lys_module **mod)
{
const char *module_data = NULL;
LYS_INFORMAT format = LYS_IN_UNKNOWN;
void (*module_data_free)(void *module_data, void *user_data) = NULL;
struct lysp_load_module_check_data check_data = {0};
- struct lys_module *ctx_latest = NULL, *m;
+ struct lys_module *ctx_latest = NULL;
struct ly_in *in;
- LY_ERR ret;
- ly_bool implement;
assert(mod && unres);
- if (ctx->flags & LY_CTX_ALL_IMPLEMENTED) {
- implement = 1;
- } else {
- implement = need_implemented;
- }
-
/*
* try to get the module from the context
*/
@@ -719,30 +707,21 @@
/* get the specific revision */
*mod = (struct lys_module *)ly_ctx_get_module(ctx, name, revision);
} else {
- if (implement) {
- /* prefer the implemented module instead of the latest one */
- *mod = (struct lys_module *)ly_ctx_get_module_implemented(ctx, name);
- }
- if (!*mod) {
- /* get the requested module of the latest revision in the context */
- *mod = (struct lys_module *)ly_ctx_get_module_latest(ctx, name);
- if (*mod && ((*mod)->latest_revision == 1)) {
- /* let us now search with callback and searchpaths to check if there is newer revision outside the context */
- ctx_latest = *mod;
- *mod = NULL;
- }
+ /* get the requested module of the latest revision in the context */
+ *mod = (struct lys_module *)ly_ctx_get_module_latest(ctx, name);
+ if (*mod && ((*mod)->latest_revision == 1)) {
+ /* let us now search with callback and searchpaths to check if there is newer revision outside the context */
+ ctx_latest = *mod;
+ *mod = NULL;
}
}
}
- /* check collision with other implemented revision */
- if (implement) {
- m = ly_ctx_get_module_implemented(ctx, name);
- if (m && (!*mod || (*mod && (m != *mod)))) {
- LOGVAL(ctx, LYVE_REFERENCE, "Module \"%s\" is already present in other implemented revision.", name);
- *mod = NULL;
- return LY_EDENIED;
- }
+ /* we have module from the current context, circular check */
+ if (*mod && (*mod)->parsed->parsing) {
+ LOGVAL(ctx, LYVE_REFERENCE, "A circular dependency (import) for module \"%s\".", name);
+ *mod = NULL;
+ return LY_EVALID;
}
/*
@@ -772,8 +751,7 @@
search_file:
if (!(ctx->flags & LY_CTX_DISABLE_SEARCHDIRS)) {
/* module was not received from the callback or there is no callback set */
- lys_module_localfile(ctx, name, revision, features, implement, NULL, NULL, ctx_latest ? 0 : 1, unres,
- (void **)mod);
+ lys_parse_localfile(ctx, name, revision, NULL, NULL, ctx_latest ? 0 : 1, unres, (void **)mod);
}
if (!*mod && (ctx->flags & LY_CTX_PREFER_SEARCHDIRS)) {
goto search_clb;
@@ -792,40 +770,9 @@
}
if (!*mod) {
- LOGVAL(ctx, LYVE_REFERENCE, "%s \"%s\" module failed.", implement ? "Loading" : "Importing", name);
+ LOGVAL(ctx, LYVE_REFERENCE, "Loading \"%s\" module failed.", name);
return LY_EVALID;
}
- } else {
- /* we have module from the current context, circular check */
- if ((*mod)->parsed->parsing) {
- LOGVAL(ctx, LYVE_REFERENCE, "A circular dependency (import) for module \"%s\".", name);
- *mod = NULL;
- return LY_EVALID;
- }
- }
-
- /*
- * module found, make sure it is implemented if should be
- */
- if (implement) {
- if (!(*mod)->implemented) {
- /* implement */
- ret = lys_set_implemented_r(*mod, features, unres);
- if (ret) {
- *mod = NULL;
- return ret;
- }
- } else if (features) {
- /* set features if different */
- ret = lys_set_features((*mod)->parsed, features);
- if (!ret) {
- /* context need to be recompiled so that feature changes are properly applied */
- unres->recompile = 1;
- } else if (ret != LY_EEXIST) {
- /* error */
- return ret;
- } /* else no feature changes */
- }
}
return LY_SUCCESS;
@@ -1014,8 +961,7 @@
search_file:
if (!(ctx->flags & LY_CTX_DISABLE_SEARCHDIRS)) {
/* submodule was not received from the callback or there is no callback set */
- lys_module_localfile(ctx, inc->name,
- inc->rev[0] ? inc->rev : NULL, NULL, 0, pctx,
+ lys_parse_localfile(ctx, inc->name, inc->rev[0] ? inc->rev : NULL, pctx,
pctx->parsed_mod->mod->name, 1, NULL, (void **)&submod);
/* update inc pointer - parsing another (YANG 1.0) submodule can cause injecting
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index 642c298..f6e1bae 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -293,21 +293,18 @@
LY_ERR lysp_check_enum_name(struct lys_parser_ctx *ctx, const char *name, size_t name_len);
/**
- * @brief Find and load a module of the given name.
+ * @brief Find source data for a specific module, parse it, and add into the context.
*
* @param[in] ctx libyang context.
* @param[in] name Name of the module to load.
* @param[in] revison Optional revision of the module to load. If NULL, the newest revision is loaded.
- * @param[in] need_implemented Whether the module should be implemented. If revision is NULL and this flag is set,
- * the implemented module in the context is returned despite it might not be of the latest revision, because in this
- * case the module of the latest revision can not be made implemented.
- * @param[in] features All the features to enable if implementing the module.
- * @param[in] unres Global unres structure for all newly implemented modules.
+ * @param[in,out] unres Global unres structure.
* @param[out] mod Created module structure.
- * @return LY_ERR value.
+ * @return LY_SUCCESS on success.
+ * @return LY_ERR on error.
*/
-LY_ERR lys_load_module(struct ly_ctx *ctx, const char *name, const char *revision, ly_bool need_implemented,
- const char **features, struct lys_glob_unres *unres, struct lys_module **mod);
+LY_ERR lys_parse_load(struct ly_ctx *ctx, const char *name, const char *revision, struct lys_glob_unres *unres,
+ struct lys_module **mod);
/**
* @brief Parse included submodules into the simply parsed YANG module.
@@ -527,37 +524,33 @@
const char *lys_datatype2str(LY_DATA_TYPE basetype);
/**
- * @brief Implement a module (just like ::lys_set_implemented()), can be called recursively.
+ * @brief Implement a module, can be called recursively.
*
* @param[in] mod Module to implement.
- * @param[in] features Array of features to enable.
+ * @param[in] features Features to set, see ::lys_set_features().
* @param[in,out] unres Global unres to add to.
- * @return LY_ERR value.
+ * @return LY_ERECOMPILE if unres->recompile dep set needs to be recompiled.
+ * @return LY_ERR on error.
*/
-LY_ERR lys_set_implemented_r(struct lys_module *mod, const char **features, struct lys_glob_unres *unres);
+LY_ERR lys_implement(struct lys_module *mod, const char **features, struct lys_glob_unres *unres);
typedef LY_ERR (*lys_custom_check)(const struct ly_ctx *ctx, struct lysp_module *mod, struct lysp_submodule *submod,
void *check_data);
/**
- * @brief Create a new module.
- *
- * It is parsed, opionally compiled, added into the context, and the latest_revision flag is updated.
+ * @brief Parse a module and add it into the context.
*
* @param[in] ctx libyang context where to process the data model.
* @param[in] in Input structure.
* @param[in] format Format of the input data (YANG or YIN).
- * @param[in] need_implemented Whether module needs to be implemented and compiled.
* @param[in] custom_check Callback to check the parsed schema before it is accepted.
* @param[in] check_data Caller's data to pass to the custom_check callback.
- * @param[in] features Array of features to enable ended with NULL. NULL for all features disabled and '*' for all enabled.
* @param[in,out] unres Global unres structure for newly implemented modules.
* @param[out] module Created module.
* @return LY_ERR value.
*/
-LY_ERR lys_create_module(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, ly_bool need_implemented,
- lys_custom_check custom_check, void *check_data, const char **features, struct lys_glob_unres *unres,
- struct lys_module **module);
+LY_ERR lys_parse_in(struct ly_ctx *ctx, struct ly_in *in, LYS_INFORMAT format, lys_custom_check custom_check,
+ void *check_data, struct lys_glob_unres *unres, struct lys_module **module);
/**
* @brief Parse submodule.