context FETAURE yang-library data generation
Also added list of deriving modules for each module.
diff --git a/src/context.c b/src/context.c
index a908e7f..1b0a7c0 100644
--- a/src/context.c
+++ b/src/context.c
@@ -11,6 +11,7 @@
*
* https://opensource.org/licenses/BSD-3-Clause
*/
+#define _GNU_SOUCRE /* asprintf */
#include "common.h"
@@ -533,6 +534,253 @@
}
}
+static LY_ERR
+ylib_feature(struct lyd_node *parent, const struct lys_module *cur_mod)
+{
+ LY_ARRAY_SIZE_TYPE i;
+ struct lyd_node *node;
+
+ if (!cur_mod->implemented) {
+ /* no features can be enabled */
+ return LY_SUCCESS;
+ }
+
+ LY_ARRAY_FOR(cur_mod->compiled->features, i) {
+ if (!(cur_mod->compiled->features[i].flags & LYS_FENABLED)) {
+ continue;
+ }
+
+ node = lyd_new_term(parent, NULL, "feature", cur_mod->compiled->features[i].name);
+ LY_CHECK_RET(!node, LY_EOTHER);
+ }
+
+ return LY_SUCCESS;
+}
+
+static LY_ERR
+ylib_deviation(struct lyd_node *parent, const struct lys_module *cur_mod, int bis)
+{
+ LY_ARRAY_SIZE_TYPE i;
+ struct lyd_node *node;
+ struct lys_module *mod;
+
+ if (!cur_mod->implemented) {
+ /* no deviations of the module for certain */
+ return LY_SUCCESS;
+ }
+
+ LY_ARRAY_FOR(cur_mod->compiled->deviated_by, i) {
+ mod = cur_mod->compiled->deviated_by[i];
+
+ if (bis) {
+ node = lyd_new_term(parent, NULL, "deviation", mod->name);
+ LY_CHECK_RET(!node, LY_EOTHER);
+ } else {
+ node = lyd_new_list(parent, NULL, "deviation", mod->name, (mod->parsed->revs ? mod->parsed->revs[0].date : ""));
+ LY_CHECK_RET(!node, LY_EOTHER);
+ }
+ }
+
+ return LY_SUCCESS;
+}
+
+static LY_ERR
+ylib_submodules(struct lyd_node *parent, const struct lys_module *cur_mod, int bis)
+{
+ LY_ARRAY_SIZE_TYPE i;
+ struct lyd_node *node, *cont;
+ struct lysp_submodule *submod;
+ int ret;
+ char *str;
+
+ LY_ARRAY_FOR(cur_mod->parsed->includes, i) {
+ submod = cur_mod->parsed->includes[i].submodule;
+
+ if (bis) {
+ cont = lyd_new_list(parent, NULL, "submodule", submod->name);
+ LY_CHECK_RET(!cont, LY_EOTHER);
+
+ if (submod->revs) {
+ node = lyd_new_term(cont, NULL, "revision", submod->revs[0].date);
+ LY_CHECK_RET(!node, LY_EOTHER);
+ }
+ } else {
+ cont = lyd_new_list(parent, NULL, "submodule", submod->name, (submod->revs ? submod->revs[0].date : ""));
+ LY_CHECK_RET(!cont, LY_EOTHER);
+ }
+
+ if (submod->filepath) {
+ ret = asprintf(&str, "file://%s", submod->filepath);
+ LY_CHECK_ERR_RET(ret == -1, LOGMEM(cur_mod->ctx), LY_EMEM);
+
+ node = lyd_new_term(cont, NULL, bis ? "location" : "schema", str);
+ LY_CHECK_RET(!node, LY_EOTHER);
+ free(str);
+ }
+ }
+
+ return LY_SUCCESS;
+}
+
+API uint16_t
+ly_ctx_get_yanglib_id(const struct ly_ctx *ctx)
+{
+ return ctx->module_set_id;
+}
+
+API struct lyd_node *
+ly_ctx_get_yanglib_data(const struct ly_ctx *ctx)
+{
+ uint32_t i;
+ int bis = 0, ret;
+ char id[8], *str;
+ const struct lys_module *mod;
+ struct lyd_node *root = NULL, *root_bis = NULL, *cont, *set_bis, *node;
+
+ LY_CHECK_ARG_RET(ctx, ctx, NULL);
+
+ mod = ly_ctx_get_module_implemented(ctx, "ietf-yang-library");
+ LY_CHECK_ERR_RET(!mod, LOGERR(ctx, LY_EINVAL, "Module \"ietf-yang-library\" is not implemented."), NULL);
+
+ if (mod->parsed->revs && !strcmp(mod->parsed->revs[0].date, "2016-06-21")) {
+ bis = 0;
+ } else if (mod->parsed->revs && !strcmp(mod->parsed->revs[0].date, IETF_YANG_LIB_REV)) {
+ bis = 1;
+ } else {
+ LOGERR(ctx, LY_EINVAL, "Incompatible ietf-yang-library version in context.");
+ return NULL;
+ }
+
+ root = lyd_new_inner(NULL, mod, "modules-state");
+ LY_CHECK_GOTO(!root, error);
+
+ if (bis) {
+ root_bis = lyd_new_inner(NULL, mod, "yang-library");
+ LY_CHECK_GOTO(!root_bis, error);
+
+ set_bis = lyd_new_list(root_bis, NULL, "module-set", "complete");
+ LY_CHECK_GOTO(!set_bis, error);
+ }
+
+ for (i = 0; i < ctx->list.count; ++i) {
+ mod = ctx->list.objs[i];
+
+ /*
+ * deprecated legacy
+ */
+ cont = lyd_new_list(root, NULL, "module", mod->name, (mod->parsed->revs ? mod->parsed->revs[0].date : ""));
+ LY_CHECK_GOTO(!cont, error);
+
+ /* schema */
+ if (mod->filepath) {
+ ret = asprintf(&str, "file://%s", mod->filepath);
+ LY_CHECK_ERR_GOTO(ret == -1, LOGMEM(ctx), error);
+
+ node = lyd_new_term(cont, NULL, "schema", str);
+ free(str);
+ LY_CHECK_GOTO(!node, error);
+ }
+
+ /* namespace */
+ node = lyd_new_term(cont, NULL, "namespace", mod->ns);
+ LY_CHECK_GOTO(!node, error);
+
+ /* feature leaf-list */
+ LY_CHECK_GOTO(ylib_feature(cont, mod), error);
+
+ /* deviation list */
+ LY_CHECK_GOTO(ylib_deviation(cont, mod, 0), error);
+
+ /* conformance-type */
+ node = lyd_new_term(cont, NULL, "conformance-type", (mod->implemented ? "implement" : "import"));
+ LY_CHECK_GOTO(!node, error);
+
+ /* submodule list */
+ LY_CHECK_GOTO(ylib_submodules(cont, mod, 0), error);
+
+ /*
+ * current revision
+ */
+ if (bis) {
+ /* name and revision */
+ if (mod->implemented) {
+ cont = lyd_new_list(set_bis, NULL, "module", mod->name);
+ LY_CHECK_GOTO(!cont, error);
+
+ if (mod->parsed->revs) {
+ node = lyd_new_term(cont, NULL, "revision", mod->parsed->revs[0].date);
+ LY_CHECK_GOTO(!node, error);
+ }
+ } else {
+ cont = lyd_new_list(set_bis, NULL, "import-only-module", mod->name,
+ (mod->parsed->revs ? mod->parsed->revs[0].date : ""));
+ LY_CHECK_GOTO(!cont, error);
+ }
+
+ /* namespace */
+ node = lyd_new_term(cont, NULL, "namespace", mod->ns);
+ LY_CHECK_GOTO(!node, error);
+
+ /* location */
+ if (mod->filepath) {
+ ret = asprintf(&str, "file://%s", mod->filepath);
+ LY_CHECK_ERR_GOTO(ret == -1, LOGMEM(ctx), error);
+
+ node = lyd_new_term(cont, NULL, "schema", str);
+ free(str);
+ LY_CHECK_GOTO(!node, error);
+ }
+
+ /* submodule list */
+ LY_CHECK_GOTO(ylib_submodules(cont, mod, 1), error);
+
+ /* feature list */
+ LY_CHECK_GOTO(ylib_feature(cont, mod), error);
+
+ /* deviation */
+ LY_CHECK_GOTO(ylib_deviation(cont, mod, 1), error);
+ }
+ }
+
+ /* IDs */
+ sprintf(id, "%u", ctx->module_set_id);
+ node = lyd_new_term(root, NULL, "module-set-id", id);
+ LY_CHECK_GOTO(!node, error);
+
+ if (bis) {
+ /* create one complete schema */
+ cont = lyd_new_list(root_bis, NULL, "schema", "complete");
+ LY_CHECK_GOTO(!cont, error);
+
+ node = lyd_new_term(cont, NULL, "module-set", "complete");
+ LY_CHECK_GOTO(!node, error);
+
+ /* content-id */
+ node = lyd_new_term(root_bis, NULL, "content-id", id);
+ LY_CHECK_GOTO(!node, error);
+ }
+
+ if (root_bis) {
+ if (lyd_insert_sibling(root_bis, root)) {
+ goto error;
+ }
+ root = root_bis;
+ root_bis = 0;
+ }
+
+ /* TODO uncomment once lefref validation works
+ if (lyd_validate(&root, NULL, LYD_VALOPT_DATA_ONLY)) {
+ goto error;
+ }*/
+
+ return root;
+
+error:
+ lyd_free_all(root);
+ lyd_free_all(root_bis);
+ return NULL;
+}
+
API void
ly_ctx_destroy(struct ly_ctx *ctx, void (*private_destructor)(const struct lysc_node *node, void *priv))
{