schema CHANGE refactor lys_module structure
- share some of the data between parsed (lysp_module) and compiled
(lysc_module) structures. It should optimize processing and make usage
more simple
- separate lysp_submodule - so far the submodules were same as parsed
modules (using a bit to differentiate). Since the lys_module structure
was optimized more for use with the data (so more focused on the
compiled schema), the lysp_module is now more interconnected with the
lys_module structure, but this cannot be done in submodules. Therefore,
the lysp_submodule was created sharing most of the members with
lysp_module (to unify parsing process) but adding some other members
which are placed into lys_module in case of lysp_module structure.
- except of the moving some of the members of lysp_module/lysc_module
into lys_module structure, the change does not affect the compiled
structures.
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 9f4b393..7ba7be7 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -124,7 +124,7 @@
goto repeat;
default:
/* we should not be here */
- LOGINT(last->module->compiled->ctx);
+ LOGINT(last->module->ctx);
return NULL;
}
@@ -255,9 +255,10 @@
struct lysc_feature *f, **df;
struct lysc_iffeature *iff;
struct ly_set *changed;
+ struct ly_ctx *ctx = mod->mod->ctx; /* shortcut */
if (!mod->features) {
- LOGERR(mod->ctx, LY_EINVAL, "Unable to switch feature since the module \"%s\" has no features.", mod->name);
+ LOGERR(ctx, LY_EINVAL, "Unable to switch feature since the module \"%s\" has no features.", mod->mod->name);
return LY_EINVAL;
}
@@ -291,7 +292,7 @@
++disabled_count;
goto next;
} else {
- LOGERR(mod->ctx, LY_EDENIED,
+ LOGERR(ctx, LY_EDENIED,
"Feature \"%s\" cannot be enabled since it is disabled by its if-feature condition(s).",
f->name);
ly_set_free(changed, NULL);
@@ -319,7 +320,7 @@
}
if (!all && !changed->count) {
- LOGERR(mod->ctx, LY_EINVAL, "Feature \"%s\" not found in module \"%s\".", name, mod->name);
+ LOGERR(ctx, LY_EINVAL, "Feature \"%s\" not found in module \"%s\".", name, mod->mod->name);
ly_set_free(changed, NULL);
return LY_EINVAL;
}
@@ -330,7 +331,7 @@
/* ... print errors */
for (u = 0; disabled_count && u < LY_ARRAY_SIZE(mod->features); ++u) {
if (!(mod->features[u].flags & LYS_FENABLED)) {
- LOGERR(mod->ctx, LY_EDENIED,
+ LOGERR(ctx, LY_EDENIED,
"Feature \"%s\" cannot be enabled since it is disabled by its if-feature condition(s).",
mod->features[u].name);
--disabled_count;
@@ -453,25 +454,80 @@
return NULL;
}
-static void
-lys_latest_switch(struct lys_module *old, struct lysp_module *new)
+struct lysp_submodule *
+lys_parse_mem_submodule(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, struct ly_parser_ctx *main_ctx,
+ LY_ERR (*custom_check)(struct ly_ctx*, struct lysp_module*, struct lysp_submodule*, void*), void *check_data)
{
- if (old->parsed) {
- new->latest_revision = old->parsed->latest_revision;
- old->parsed->latest_revision = 0;
+ LY_ERR ret = LY_EINVAL;
+ struct lysp_submodule *submod = NULL, *latest_sp;
+ struct ly_parser_ctx context = {0};
+
+ LY_CHECK_ARG_RET(ctx, ctx, data, NULL);
+
+ context.ctx = ctx;
+ context.line = 1;
+
+ /* map the typedefs and groupings list from main context to the submodule's context */
+ memcpy(&context.tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
+ memcpy(&context.grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
+
+ switch (format) {
+ case LYS_IN_YIN:
+ /* TODO not yet supported
+ mod = yin_read_module();
+ */
+ break;
+ case LYS_IN_YANG:
+ ret = yang_parse_submodule(&context, data, &submod);
+ break;
+ default:
+ LOGERR(context.ctx, LY_EINVAL, "Invalid schema input format.");
+ break;
}
- if (old->compiled) {
- new->latest_revision = old->parsed->latest_revision;
- old->compiled->latest_revision = 0;
+ LY_CHECK_RET(ret, NULL);
+
+ /* make sure that the newest revision is at position 0 */
+ lysp_sort_revisions(submod->revs);
+
+ if (custom_check) {
+ LY_CHECK_GOTO(custom_check(context.ctx, NULL, submod, check_data), error);
}
+
+ /* decide the latest revision */
+ latest_sp = ly_ctx_get_submodule(context.ctx, submod->belongsto, submod->name, NULL);
+ if (latest_sp) {
+ if (submod->revs) {
+ if (!latest_sp->revs) {
+ /* latest has no revision, so mod is anyway newer */
+ submod->latest_revision = latest_sp->latest_revision;
+ latest_sp->latest_revision = 0;
+ } else {
+ if (strcmp(submod->revs[0].date, latest_sp->revs[0].date) > 0) {
+ submod->latest_revision = latest_sp->latest_revision;
+ latest_sp->latest_revision = 0;
+ }
+ }
+ }
+ } else {
+ submod->latest_revision = 1;
+ }
+
+ /* remap possibly changed and reallocated typedefs and groupings list back to the main context */
+ memcpy(&main_ctx->tpdfs_nodes, &context.tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
+ memcpy(&main_ctx->grps_nodes, &context.grps_nodes, sizeof main_ctx->grps_nodes);
+
+ return submod;
+error:
+ lysp_submodule_free(ctx, submod);
+ return NULL;
}
struct lys_module *
-lys_parse_mem_(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, int implement, struct ly_parser_ctx *main_ctx,
- LY_ERR (*custom_check)(struct ly_ctx *ctx, struct lysp_module *mod, void *data), void *check_data)
+lys_parse_mem_module(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format, int implement,
+ LY_ERR (*custom_check)(struct ly_ctx *ctx, struct lysp_module *mod, struct lysp_submodule *submod, void *data),
+ void *check_data)
{
struct lys_module *mod = NULL, *latest, *mod_dup;
- struct lysp_module *latest_p;
struct lysp_import *imp;
struct lysp_include *inc;
LY_ERR ret = LY_EINVAL;
@@ -483,95 +539,64 @@
context.ctx = ctx;
context.line = 1;
- if (main_ctx) {
- /* map the typedefs and groupings list from main context to the submodule's context */
- memcpy(&context.tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
- memcpy(&context.grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
- }
-
mod = calloc(1, sizeof *mod);
LY_CHECK_ERR_RET(!mod, LOGMEM(ctx), NULL);
+ mod->ctx = ctx;
switch (format) {
case LYS_IN_YIN:
/* TODO not yet supported
- mod = yin_read_module(ctx, data, revision, implement);
+ mod = yin_read_module();
*/
break;
case LYS_IN_YANG:
- ret = yang_parse(&context, data, &mod->parsed);
+ ret = yang_parse_module(&context, data, mod);
break;
default:
LOGERR(ctx, LY_EINVAL, "Invalid schema input format.");
break;
}
- LY_CHECK_ERR_RET(ret, free(mod), NULL);
+ LY_CHECK_ERR_RET(ret, lys_module_free(mod, NULL), NULL);
/* make sure that the newest revision is at position 0 */
lysp_sort_revisions(mod->parsed->revs);
+ if (custom_check) {
+ LY_CHECK_GOTO(custom_check(ctx, mod->parsed, NULL, check_data), error);
+ }
+
if (implement) {
/* mark the loaded module implemented */
- if (ly_ctx_get_module_implemented(ctx, mod->parsed->name)) {
- LOGERR(ctx, LY_EDENIED, "Module \"%s\" is already implemented in the context.", mod->parsed->name);
+ if (ly_ctx_get_module_implemented(ctx, mod->name)) {
+ LOGERR(ctx, LY_EDENIED, "Module \"%s\" is already implemented in the context.", mod->name);
goto error;
}
- mod->parsed->implemented = 1;
+ mod->implemented = 1;
}
- if (custom_check) {
- LY_CHECK_GOTO(custom_check(ctx, mod->parsed, check_data), error);
- }
-
- if (mod->parsed->submodule) { /* submodule */
- if (!main_ctx) {
- LOGERR(ctx, LY_EDENIED, "Input data contains submodule \"%s\" which cannot be parsed directly without its main module.",
- mod->parsed->name);
- goto error;
- }
- /* decide the latest revision */
- latest_p = ly_ctx_get_submodule(ctx, mod->parsed->belongsto, mod->parsed->name, NULL);
- if (latest_p) {
+ /* check for duplicity in the context */
+ mod_dup = (struct lys_module*)ly_ctx_get_module(ctx, mod->name, mod->parsed->revs ? mod->parsed->revs[0].date : NULL);
+ if (mod_dup) {
+ if (mod_dup->parsed) {
+ /* error */
if (mod->parsed->revs) {
- if (!latest_p->revs) {
- /* latest has no revision, so mod is anyway newer */
- mod->parsed->latest_revision = latest_p->latest_revision;
- latest_p->latest_revision = 0;
- } else {
- if (strcmp(mod->parsed->revs[0].date, latest_p->revs[0].date) > 0) {
- mod->parsed->latest_revision = latest_p->latest_revision;
- latest_p->latest_revision = 0;
- }
- }
- }
- } else {
- mod->parsed->latest_revision = 1;
- }
- /* remap possibly changed and reallocated typedefs and groupings list back to the main context */
- memcpy(&main_ctx->tpdfs_nodes, &context.tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
- memcpy(&main_ctx->grps_nodes, &context.grps_nodes, sizeof main_ctx->grps_nodes);
- } else { /* module */
- /* check for duplicity in the context */
- mod_dup = (struct lys_module*)ly_ctx_get_module(ctx, mod->parsed->name, mod->parsed->revs ? mod->parsed->revs[0].date : NULL);
- if (mod_dup) {
- if (mod_dup->parsed) {
- /* error */
- if (mod->parsed->revs) {
- LOGERR(ctx, LY_EEXIST, "Module \"%s\" of revision \"%s\" is already present in the context.",
- mod->parsed->name, mod->parsed->revs[0].date);
- } else {
- LOGERR(ctx, LY_EEXIST, "Module \"%s\" with no revision is already present in the context.",
- mod->parsed->name);
- }
- goto error;
+ LOGERR(ctx, LY_EEXIST, "Module \"%s\" of revision \"%s\" is already present in the context.",
+ mod->name, mod->parsed->revs[0].date);
} else {
- /* add the parsed data to the currently compiled-only module in the context */
- mod_dup->parsed = mod->parsed;
- free(mod);
- mod = mod_dup;
- goto finish_parsing;
+ LOGERR(ctx, LY_EEXIST, "Module \"%s\" with no revision is already present in the context.",
+ mod->name);
}
+ goto error;
+ } else {
+ /* add the parsed data to the currently compiled-only module in the context */
+ mod_dup->parsed = mod->parsed;
+ mod_dup->parsed->mod = mod_dup;
+ mod->parsed = NULL;
+ lys_module_free(mod, NULL);
+ mod = mod_dup;
+ goto finish_parsing;
}
+ }
#if 0
/* hack for NETCONF's edit-config's operation attribute. It is not defined in the schema, but since libyang
@@ -579,7 +604,7 @@
* internal part of libyang, we cannot add the annotation into the schema source, but we do it here to have
* the anotation definitions available in the internal schema structure. There is another hack in schema
* printers to do not print this internally added annotation. */
- if (mod && ly_strequal(mod->name, "ietf-netconf", 0)) {
+ if (ly_strequal(mod->name, "ietf-netconf", 0)) {
if (lyp_add_ietf_netconf_annotations(mod)) {
lys_free(mod, NULL, 1, 1);
return NULL;
@@ -587,53 +612,52 @@
}
#endif
- /* decide the latest revision */
- latest = (struct lys_module*)ly_ctx_get_module_latest(ctx, mod->parsed->name);
- if (latest) {
- if (mod->parsed->revs) {
- if ((latest->parsed && !latest->parsed->revs) || (!latest->parsed && !latest->compiled->revision)) {
- /* latest has no revision, so mod is anyway newer */
- lys_latest_switch(latest, mod->parsed);
- } else {
- if (strcmp(mod->parsed->revs[0].date, latest->parsed ? latest->parsed->revs[0].date : latest->compiled->revision) > 0) {
- lys_latest_switch(latest, mod->parsed);
- }
- }
+ /* decide the latest revision */
+ latest = (struct lys_module*)ly_ctx_get_module_latest(ctx, mod->name);
+ if (latest) {
+ if (mod->parsed->revs) {
+ if ((latest->parsed && !latest->parsed->revs) || (!latest->parsed && !latest->compiled->revision)) {
+ /* latest has no revision, so mod is anyway newer */
+ mod->latest_revision = latest->latest_revision;
+ latest->latest_revision = 0;
+ } else if (strcmp(mod->parsed->revs[0].date, latest->parsed ? latest->parsed->revs[0].date : latest->compiled->revision) > 0) {
+ mod->latest_revision = latest->latest_revision;
+ latest->latest_revision = 0;
}
- } else {
- mod->parsed->latest_revision = 1;
}
+ } else {
+ mod->latest_revision = 1;
+ }
- /* add into context */
- ly_set_add(&ctx->list, mod, LY_SET_OPT_USEASLIST);
+ /* add into context */
+ ly_set_add(&ctx->list, mod, LY_SET_OPT_USEASLIST);
finish_parsing:
- /* resolve imports */
- mod->parsed->parsing = 1;
- LY_ARRAY_FOR(mod->parsed->imports, u) {
- imp = &mod->parsed->imports[u];
- if (!imp->module && lysp_load_module(ctx, imp->name, imp->rev[0] ? imp->rev : NULL, 0, 0, &imp->module)) {
- goto error_ctx;
- }
- /* check for importing the same module twice */
- for (i = 0; i < u; ++i) {
- if (imp->module == mod->parsed->imports[i].module) {
- LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_REFERENCE, "Single revision of the module \"%s\" referred twice.", imp->name);
- goto error_ctx;
- }
- }
+ /* resolve imports */
+ mod->parsed->parsing = 1;
+ LY_ARRAY_FOR(mod->parsed->imports, u) {
+ imp = &mod->parsed->imports[u];
+ if (!imp->module && lysp_load_module(ctx, imp->name, imp->rev[0] ? imp->rev : NULL, 0, 0, &imp->module)) {
+ goto error_ctx;
}
- LY_ARRAY_FOR(mod->parsed->includes, u) {
- inc = &mod->parsed->includes[u];
- if (!inc->submodule && lysp_load_submodule(&context, mod->parsed, inc)) {
+ /* check for importing the same module twice */
+ for (i = 0; i < u; ++i) {
+ if (imp->module == mod->parsed->imports[i].module) {
+ LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_REFERENCE, "Single revision of the module \"%s\" referred twice.", imp->name);
goto error_ctx;
}
}
- mod->parsed->parsing = 0;
-
- /* check name collisions - typedefs and groupings */
- LY_CHECK_GOTO(lysp_check_typedefs(&context), error_ctx);
}
+ LY_ARRAY_FOR(mod->parsed->includes, u) {
+ inc = &mod->parsed->includes[u];
+ if (!inc->submodule && lysp_load_submodule(&context, mod->parsed, inc)) {
+ goto error_ctx;
+ }
+ }
+ mod->parsed->parsing = 0;
+
+ /* check name collisions - typedefs and groupings */
+ LY_CHECK_GOTO(lysp_check_typedefs(&context, mod->parsed), error_ctx);
return mod;
@@ -648,7 +672,7 @@
API struct lys_module *
lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
{
- return lys_parse_mem_(ctx, data, format, 1, NULL, NULL, NULL);
+ return lys_parse_mem_module(ctx, data, format, 1, NULL, NULL);
}
static void
@@ -672,11 +696,14 @@
#endif
}
-struct lys_module *
+void *
lys_parse_fd_(struct ly_ctx *ctx, int fd, LYS_INFORMAT format, int implement, struct ly_parser_ctx *main_ctx,
- LY_ERR (*custom_check)(struct ly_ctx *ctx, struct lysp_module *mod, void *data), void *check_data)
+ LY_ERR (*custom_check)(struct ly_ctx *ctx, struct lysp_module *mod, struct lysp_submodule *submod, void *data),
+ void *check_data)
{
- struct lys_module *mod;
+ void *result;
+ struct lys_module *mod = NULL;
+ struct lysp_submodule *submod = NULL;
size_t length;
char *addr;
@@ -692,25 +719,48 @@
return NULL;
}
- mod = lys_parse_mem_(ctx, addr, format, implement, main_ctx, custom_check, check_data);
+ if (main_ctx) {
+ result = submod = lys_parse_mem_submodule(ctx, addr, format, main_ctx, custom_check, check_data);
+ } else {
+ result = mod = lys_parse_mem_module(ctx, addr, format, implement, custom_check, check_data);
+ }
ly_munmap(addr, length);
- if (mod && !mod->parsed->filepath) {
- lys_parse_set_filename(ctx, &mod->parsed->filepath, fd);
+ if (mod && !mod->filepath) {
+ lys_parse_set_filename(ctx, &mod->filepath, fd);
+ } else if (submod && !submod->filepath) {
+ lys_parse_set_filename(ctx, &submod->filepath, fd);
}
- return mod;
+ return result;
+}
+
+struct lys_module *
+lys_parse_fd_module(struct ly_ctx *ctx, int fd, LYS_INFORMAT format, int implement,
+ LY_ERR (*custom_check)(struct ly_ctx *ctx, struct lysp_module *mod, struct lysp_submodule *submod, void *data),
+ void *check_data)
+{
+ return (struct lys_module*)lys_parse_fd_(ctx, fd, format, implement, NULL, custom_check, check_data);
+}
+
+struct lysp_submodule *
+lys_parse_fd_submodule(struct ly_ctx *ctx, int fd, LYS_INFORMAT format, struct ly_parser_ctx *main_ctx,
+ LY_ERR (*custom_check)(struct ly_ctx *ctx, struct lysp_module *mod, struct lysp_submodule *submod, void *data),
+ void *check_data)
+{
+ assert(main_ctx);
+ return (struct lysp_submodule*)lys_parse_fd_(ctx, fd, format, 0, main_ctx, custom_check, check_data);
}
API struct lys_module *
lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
{
- return lys_parse_fd_(ctx, fd, format, 1, NULL, NULL, NULL);
+ return lys_parse_fd_module(ctx, fd, format, 1, NULL, NULL);
}
struct lys_module *
-lys_parse_path_(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format, int implement, struct ly_parser_ctx *main_ctx,
- LY_ERR (*custom_check)(struct ly_ctx *ctx, struct lysp_module *mod, void *data), void *check_data)
+lys_parse_path_(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format, int implement,
+ LY_ERR (*custom_check)(struct ly_ctx *ctx, struct lysp_module *mod, struct lysp_submodule *submod, void *data), void *check_data)
{
int fd;
struct lys_module *mod;
@@ -722,7 +772,7 @@
fd = open(path, O_RDONLY);
LY_CHECK_ERR_RET(fd == -1, LOGERR(ctx, LY_ESYS, "Opening file \"%s\" failed (%s).", path, strerror(errno)), NULL);
- mod = lys_parse_fd_(ctx, fd, format, implement, main_ctx, custom_check, check_data);
+ mod = lys_parse_fd_module(ctx, fd, format, implement, custom_check, check_data);
close(fd);
LY_CHECK_RET(!mod, NULL);
@@ -737,10 +787,10 @@
dot = strrchr(filename, '.');
/* name */
- len = strlen(mod->parsed->name);
- if (strncmp(filename, mod->parsed->name, len) ||
+ len = strlen(mod->name);
+ if (strncmp(filename, mod->name, len) ||
((rev && rev != &filename[len]) || (!rev && dot != &filename[len]))) {
- LOGWRN(ctx, "File name \"%s\" does not match module name \"%s\".", filename, mod->parsed->name);
+ LOGWRN(ctx, "File name \"%s\" does not match module name \"%s\".", filename, mod->name);
}
if (rev) {
len = dot - ++rev;
@@ -750,13 +800,13 @@
}
}
- if (!mod->parsed->filepath) {
+ if (!mod->filepath) {
/* store URI */
char rpath[PATH_MAX];
if (realpath(path, rpath) != NULL) {
- mod->parsed->filepath = lydict_insert(ctx, rpath, 0);
+ mod->filepath = lydict_insert(ctx, rpath, 0);
} else {
- mod->parsed->filepath = lydict_insert(ctx, path, 0);
+ mod->filepath = lydict_insert(ctx, path, 0);
}
}
@@ -766,7 +816,7 @@
API struct lys_module *
lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
{
- return lys_parse_path_(ctx, path, format, 1, NULL, NULL, NULL);
+ return lys_parse_path_(ctx, path, format, 1, NULL, NULL);
}
API LY_ERR