plugins_exts FEATURE added printer_tree callbacks
A new interface has been added that allows the plugin to add nodes
to print a YANG tree diagram and also change the appearance of nodes.
diff --git a/src/plugins_exts/schema_mount.c b/src/plugins_exts/schema_mount.c
index 3bc16f9..6a3c86e 100644
--- a/src/plugins_exts/schema_mount.c
+++ b/src/plugins_exts/schema_mount.c
@@ -57,6 +57,11 @@
} inln; /**< inline mount points */
};
+struct sprinter_tree_priv {
+ struct ly_ctx *ext_ctx;
+ struct ly_set *refs;
+};
+
#define EXT_LOGERR_MEM_RET(cctx, ext) \
lyplg_ext_compile_log(cctx, ext, LY_LLERR, LY_EMEM, "Memory allocation failed (%s:%d).", __FILE__, __LINE__); \
return LY_EMEM
@@ -951,6 +956,202 @@
return res;
}
+static void
+schema_mount_spriter_tree_free(void *priv)
+{
+ struct sprinter_tree_priv *st_priv;
+
+ st_priv = priv;
+ ly_set_free(st_priv->refs, NULL);
+ ly_ctx_destroy(st_priv->ext_ctx);
+ free(st_priv);
+}
+
+static LY_ERR
+schema_mount_sprinter_tree_cnode_override_mounted(const struct lysc_node *node, const void *UNUSED(plugin_priv),
+ ly_bool *UNUSED(skip), const char **UNUSED(flags), const char **add_opts)
+{
+ if (!node->parent) {
+ *add_opts = "/";
+ }
+
+ return LY_SUCCESS;
+}
+
+static LY_ERR
+schema_mount_sprinter_tree_pnode_override_mounted(const struct lysp_node *node, const void *UNUSED(plugin_priv),
+ ly_bool *UNUSED(skip), const char **UNUSED(flags), const char **add_opts)
+{
+ if (!node->parent) {
+ *add_opts = "/";
+ }
+
+ return LY_SUCCESS;
+}
+
+static LY_ERR
+schema_mount_sprinter_tree_node_override_parent_refs(const struct lysc_node *node, const void *plugin_priv,
+ ly_bool *skip, const char **UNUSED(flags), const char **add_opts)
+{
+ uint32_t i;
+ const struct ly_set *refs;
+ const struct lysc_module *mod;
+ struct lysc_node *ref, *iter;
+
+ refs = ((struct sprinter_tree_priv *)plugin_priv)->refs;
+ mod = node->module->compiled;
+
+ /* Assume the @p node will be skipped. */
+ *skip = 1;
+ for (i = 0; (i < refs->count) && *skip; i++) {
+ ref = refs->snodes[i];
+ if (ref->module->compiled != mod) {
+ /* parent-reference points to different module */
+ continue;
+ }
+
+ for (iter = ref; iter; iter = iter->parent) {
+ if (iter == node) {
+ /* @p node is not skipped because it is parent-rererence node or his parent */
+ *skip = 0;
+ break;
+ }
+ }
+ }
+
+ if (!*skip && !node->parent) {
+ /* top-node has additional opts */
+ *add_opts = "@";
+ }
+
+ return LY_SUCCESS;
+}
+
+static LY_ERR
+schema_mount_sprinter_ptree(struct lysp_ext_instance *UNUSED(ext), const struct lyspr_tree_ctx *ctx,
+ const char **flags, const char **UNUSED(add_opts))
+{
+ if (!ctx) {
+ *flags = "mp";
+ }
+
+ return LY_SUCCESS;
+}
+
+static LY_ERR
+schema_mount_sprinter_ctree(struct lysc_ext_instance *ext, const struct lyspr_tree_ctx *ctx,
+ const char **flags, const char **UNUSED(add_opts))
+{
+ LY_ERR rc = LY_SUCCESS;
+ struct ly_ctx *ext_ctx = NULL;
+ const struct lys_module *mod;
+ struct ly_set *refs = NULL;
+ struct lysc_node *tree1, *tree2;
+ uint32_t i, j;
+ ly_bool from_parent_ref, is_first;
+ struct sprinter_tree_priv *st_priv;
+
+ if (!ctx) {
+ *flags = "mp";
+ return LY_SUCCESS;
+ }
+
+ if (lyplg_ext_schema_mount_create_context(ext, &ext_ctx)) {
+ /* Void mount point */
+ return LY_SUCCESS;
+ }
+
+ rc = lyplg_ext_schema_mount_get_parent_ref(ext, &refs);
+ LY_CHECK_GOTO(rc, cleanup);
+
+ /* build new list of modules to print. This list will omit internal
+ * modules, modules with no nodes (e.g., iana-if-types) and modules
+ * that were loaded as the result of a parent-reference.
+ */
+ i = ly_ctx_internal_modules_count(ext_ctx);
+ while ((mod = ly_ctx_get_module_iter(ext_ctx, &i))) {
+ from_parent_ref = 0;
+
+ for (j = 0; refs && j < refs->count; j++) {
+ if (!strcmp(mod->ns, refs->snodes[j]->module->ns)) {
+ from_parent_ref = 1;
+ break;
+ }
+ }
+ if (from_parent_ref) {
+ /* Modules loaded as the result of a parent-reference are added later. */
+ continue;
+ }
+
+ /* Add data nodes, rpcs and notifications. */
+ if ((ext_ctx->flags & LY_CTX_SET_PRIV_PARSED) && mod->compiled) {
+ /* For compiled module. */
+ rc = lyplg_ext_sprinter_ctree_add_nodes(ctx, mod->compiled->data,
+ schema_mount_sprinter_tree_cnode_override_mounted);
+ LY_CHECK_GOTO(rc, cleanup);
+ if (mod->compiled->rpcs) {
+ rc = lyplg_ext_sprinter_ctree_add_nodes(ctx, &mod->compiled->rpcs->node,
+ schema_mount_sprinter_tree_cnode_override_mounted);
+ }
+ LY_CHECK_GOTO(rc, cleanup);
+ if (mod->compiled->notifs) {
+ rc = lyplg_ext_sprinter_ctree_add_nodes(ctx, &mod->compiled->notifs->node,
+ schema_mount_sprinter_tree_cnode_override_mounted);
+ }
+ LY_CHECK_GOTO(rc, cleanup);
+ } else {
+ /* For parsed module. */
+ rc = lyplg_ext_sprinter_ptree_add_nodes(ctx, mod->parsed->data,
+ schema_mount_sprinter_tree_pnode_override_mounted);
+ LY_CHECK_GOTO(rc, cleanup);
+ if (mod->parsed->rpcs) {
+ rc = lyplg_ext_sprinter_ptree_add_nodes(ctx, &mod->parsed->rpcs->node,
+ schema_mount_sprinter_tree_pnode_override_mounted);
+ }
+ LY_CHECK_GOTO(rc, cleanup);
+ if (mod->parsed->notifs) {
+ rc = lyplg_ext_sprinter_ptree_add_nodes(ctx, &mod->parsed->notifs->node,
+ schema_mount_sprinter_tree_pnode_override_mounted);
+ }
+ LY_CHECK_GOTO(rc, cleanup);
+ }
+ }
+
+ /* Add modules loaded as the result of a parent-reference. */
+ for (i = 0; refs && (i < refs->count); i++) {
+ tree1 = refs->snodes[i]->module->compiled->data;
+
+ /* Add data nodes from the module only once. */
+ is_first = 1;
+ for (j = 0; j < i; j++) {
+ tree2 = refs->snodes[j]->module->compiled->data;
+ if (tree1 == tree2) {
+ is_first = 0;
+ break;
+ }
+ }
+ if (is_first) {
+ /* Add all data nodes but unavailable nodes are skipped in the callback. */
+ rc = lyplg_ext_sprinter_ctree_add_nodes(ctx, tree1, schema_mount_sprinter_tree_node_override_parent_refs);
+ LY_CHECK_GOTO(rc, cleanup);
+ }
+ }
+
+ /* Add private plugin data. */
+ st_priv = calloc(1, sizeof(*st_priv));
+ st_priv->ext_ctx = ext_ctx;
+ st_priv->refs = refs;
+ rc = lyplg_ext_sprinter_tree_set_priv(ctx, st_priv, schema_mount_spriter_tree_free);
+
+cleanup:
+ if (rc) {
+ ly_set_free(refs, NULL);
+ ly_ctx_destroy(ext_ctx);
+ }
+
+ return rc;
+}
+
/**
* @brief Plugin descriptions for the Yang Schema Mount extension.
*
@@ -968,6 +1169,8 @@
.plugin.parse = schema_mount_parse,
.plugin.compile = schema_mount_compile,
.plugin.printer_info = NULL,
+ .plugin.printer_ctree = schema_mount_sprinter_ctree,
+ .plugin.printer_ptree = schema_mount_sprinter_ptree,
.plugin.node = NULL,
.plugin.snode = schema_mount_snode,
.plugin.validate = schema_mount_validate,