schema parser CHANGE simplify module importing
better integrate functionality of selecting module to import (if read
a module from file or use one in context).
Parsing errors of the imported modules were hidden and it wasn't clear
why the main module is not loaded.
diff --git a/src/common.h b/src/common.h
index 9a7a3e2..1998c85 100644
--- a/src/common.h
+++ b/src/common.h
@@ -235,8 +235,17 @@
void ly_vlog_build_path_reverse(enum LY_VLOG_ELEM elem_type, const void *elem, char *path, uint16_t *index);
-struct lys_module *ly_ctx_load_sub_module(struct ly_ctx *ctx, struct lys_module *module, const char *name,
- const char *revision, int implement, struct unres_schema *unres);
+/*
+ * - if \p module specified, it searches for submodules, they can be loaded only from a file or via module callback,
+ * they cannot be get from context
+ * - if \p module is not specified
+ * - if specific revision is specified, the first try is to get module from the context
+ * - if no specific revision is specified, it tries to get the newest module - first it searches for the file and
+ * then checks that the schema loaded from the same source isn't already in context. If the source wasn't
+ * previously loaded, it is parsed.
+ */
+const struct lys_module *ly_ctx_load_sub_module(struct ly_ctx *ctx, struct lys_module *module, const char *name,
+ const char *revision, int implement, struct unres_schema *unres);
/**
* @brief Basic functionality like strpbrk(3). However, it searches string \p s
diff --git a/src/context.c b/src/context.c
index 2d5fc86..719fd19 100644
--- a/src/context.c
+++ b/src/context.c
@@ -357,18 +357,18 @@
return ctx->module_clb;
}
-struct lys_module *
+const struct lys_module *
ly_ctx_load_sub_module(struct ly_ctx *ctx, struct lys_module *module, const char *name, const char *revision,
int implement, struct unres_schema *unres)
{
- struct lys_module *mod;
+ const struct lys_module *mod;
char *module_data;
int i;
void (*module_data_free)(void *module_data) = NULL;
LYS_INFORMAT format = LYS_IN_UNKNOWN;
- /* exception for internal modules */
if (!module) {
+ /* exception for internal modules */
for (i = 0; i < INTERNAL_MODULES_COUNT; i++) {
if (ly_strequal(name, internal_modules[i].name, 0)) {
if (!revision || ly_strequal(revision, internal_modules[i].revision, 0)) {
@@ -377,6 +377,32 @@
}
}
}
+ if (revision) {
+ /* try to get the schema with the specific revision from the context */
+ mod = ly_ctx_get_module(ctx, name, revision);
+ if (mod) {
+ /* we get such a module, make it implemented */
+ if (lys_set_implemented(mod)) {
+ /* the schema cannot be implemented */
+ mod = NULL;
+ }
+ return mod;
+ }
+ }
+ } else {
+ /* searching for submodule, try if it is already loaded */
+ mod = (struct lys_module *)ly_ctx_get_submodule2(module, name);
+ if (mod) {
+ if (!revision || (mod->rev_size && ly_strequal(mod->rev[0].date, revision, 0))) {
+ /* success */
+ return mod;
+ } else {
+ /* there is already another revision of the submodule */
+ LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, mod->rev[0].date, "revision");
+ LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Multiple revisions of a submodule included.");
+ return NULL;
+ }
+ }
}
if (ctx->module_clb) {
@@ -387,8 +413,15 @@
module_data = ctx->module_clb(name, revision, NULL, NULL, ctx->module_clb_data, &format, &module_data_free);
}
if (!module_data) {
- LOGERR(0, "User module retrieval callback failed!");
- return NULL;
+ if (module || revision) {
+ /* we already know that the specified revision is not present in context, and we have no other
+ * option in case of submodules */
+ LOGERR(LY_ESYS, "User module retrieval callback failed!");
+ return NULL;
+ } else {
+ /* get the newest revision from the context */
+ return ly_ctx_get_module(ctx, name, revision);
+ }
}
if (module) {
diff --git a/src/parser.c b/src/parser.c
index 89646cf..5e06ce9 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -223,22 +223,6 @@
struct lys_module *result = NULL;
int localsearch = 0;
- if (module) {
- /* searching for submodule, try if it is already loaded */
- result = (struct lys_module *)ly_ctx_get_submodule2(module, name);
- if (result) {
- if (!revision || (result->rev_size && ly_strequal(result->rev[0].date, revision, 0))) {
- /* success */
- return result;
- } else {
- /* there is already another revision of the submodule */
- LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, result->rev[0].date, "revision");
- LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Multiple revisions of a submodule included.");
- return NULL;
- }
- }
- }
-
len = strlen(name);
if (ctx->models.search_path) {
/* try context's search_path first */
@@ -259,7 +243,7 @@
dir_len = strlen(wd);
LOGVRB("Searching for \"%s\" in %s.", name, wd);
if (!dir) {
- LOGWRN("Unable to open directory \"%s\" for searching referenced modules (%s)",
+ LOGWRN("Unable to open directory \"%s\" for searching referenced modules (%s).",
wd, strerror(errno));
} else {
while ((file = readdir(dir))) {
@@ -342,8 +326,13 @@
}
if (!match_name) {
- LOGERR(LY_ESYS, "Data model \"%s\" not found (neither in search path \"%s\" nor in working directory \"%s\")",
- name, ctx->models.search_path, wd);
+ if (!module) {
+ result = (struct lys_module *)ly_ctx_get_module(ctx, name, revision);
+ }
+ if (!result) {
+ LOGERR(LY_ESYS, "Data model \"%s\" not found.",
+ name, ctx->models.search_path, wd);
+ }
goto cleanup;
}
@@ -351,18 +340,20 @@
/* cut the format for now */
strrchr(match_name, '.')[1] = '\0';
- /* check that the same file was not already loaded */
- for (i = 0; i < ctx->models.used; ++i) {
- if (ctx->models.list[i]->filepath && !strcmp(name, ctx->models.list[i]->name)
- && !strncmp(match_name, ctx->models.list[i]->filepath, strlen(match_name))) {
- result = ctx->models.list[i];
- if (implement && !result->implemented) {
- /* make it implemented now */
- if (lys_set_implemented(result)) {
- result = NULL;
+ /* check that the same file was not already loaded - it make sense only in case of loading the newest revision */
+ if (!revision) {
+ for (i = 0; i < ctx->models.used; ++i) {
+ if (ctx->models.list[i]->filepath && !strcmp(name, ctx->models.list[i]->name)
+ && !strncmp(match_name, ctx->models.list[i]->filepath, strlen(match_name))) {
+ result = ctx->models.list[i];
+ if (implement && !result->implemented) {
+ /* make it implemented now */
+ if (lys_set_implemented(result)) {
+ result = NULL;
+ }
}
+ goto cleanup;
}
- goto cleanup;
}
}
@@ -1809,10 +1800,7 @@
{
int i;
struct lys_module *dup = NULL;
- LY_LOG_LEVEL verb;
- /* store current log level, some magic is happening with it here */
- verb = ly_log_level;
/* check for importing a single module in multiple revisions */
for (i = 0; i < module->imp_size; i++) {
@@ -1826,10 +1814,8 @@
/* the already imported module has
* - no revision, but here we require some
* - different revision than the one required here */
- ly_verb(LY_LLERR);
LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "import");
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Importing multiple revisions of module \"%s\".", value);
- ly_verb(verb);
return -1;
} else if (!imp->rev[0]) {
/* no revision, remember the duplication, but check revisions after loading the module
@@ -1851,44 +1837,15 @@
return -1;
}
- /* try to load the module */
- if (!imp->rev[0]) {
- /* no revision specified, try to load the newest module from the search locations into the context */
- ly_verb(LY_LLSILENT);
- ly_ctx_load_sub_module(module->ctx, NULL, value, imp->rev[0] ? imp->rev : NULL, 0, NULL);
- ly_verb(verb);
- if (ly_errno == LY_ESYS) {
- /* it is ok, that the e.g. input file was not found */
- ly_errno = LY_SUCCESS;
- } else if (ly_errno != LY_SUCCESS) {
- /* but it is not ok if e.g. the input data were found and they are invalid */
- lyp_check_circmod_pop(module);
- /* really print this, even if we are recursively in this function */
- ly_verb(LY_LLERR);
- LOGERR(ly_errno, ly_errmsg());
- LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
- ly_verb(verb);
- return -1;
- }
-
- /* If the loaded module (if any) is really the newest, it will be loaded on the next line
- * by ly_ctx_get_module() */
- }
- imp->module = (struct lys_module *)ly_ctx_get_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
- if (!imp->module) {
- /* whether to use a user callback is decided in the function */
- imp->module = (struct lys_module *)ly_ctx_load_sub_module(module->ctx, NULL, value, imp->rev[0] ? imp->rev : NULL, 0, NULL);
- }
+ /* load module - in specific situations it tries to get the module from the context */
+ imp->module = (struct lys_module *)ly_ctx_load_sub_module(module->ctx, NULL, value, imp->rev[0] ? imp->rev : NULL, 0, NULL);
/* update the list of currently being parsed modules */
lyp_check_circmod_pop(module);
/* check the result */
if (!imp->module) {
- ly_verb(LY_LLERR);
- LOGERR(ly_errno, ly_errmsg());
LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
- ly_verb(verb);
return -1;
}
@@ -1900,10 +1857,8 @@
/* - modules are not the same
* - one of modules has no revision (except they both has no revision)
* - revisions of the modules are not the same */
- ly_verb(LY_LLERR);
LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "import");
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Importing multiple revisions of module \"%s\".", value);
- ly_verb(verb);
return -1;
}
}