tree printer CHANGE new tree-rfc format and some other options added
Added option for not printing leafref targets, not resolving uses
groupings and print uses instead, printing only subtree, and
limiting line length. New test of this also added.
diff --git a/src/parser_yang.c b/src/parser_yang.c
index 6b6fc88..b67234b 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -620,7 +620,7 @@
int rc, ret = -1;
unsigned int i, j;
int8_t req;
- const char *name, *value;
+ const char *name, *value, *module_name = NULL;
LY_DATA_TYPE base = 0, base_tmp;
struct lys_node *siter;
struct lys_type *dertype;
@@ -643,29 +643,33 @@
/* module name */
name = value;
if (value[i]) {
- type->module_name = lydict_insert(module->ctx, value, i);
+ module_name = lydict_insert(module->ctx, value, i);
name += i;
if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
+ lydict_remove(module->ctx, module_name);
lydict_remove(module->ctx, value);
goto error;
}
++name;
}
- rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
+ rc = resolve_superior_type(name, module_name, module, parent, &type->der);
if (rc == -1) {
- LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
+ LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, module_name);
+ lydict_remove(module->ctx, module_name);
lydict_remove(module->ctx, value);
goto error;
/* the type could not be resolved or it was resolved to an unresolved typedef or leafref */
} else if (rc == EXIT_FAILURE) {
LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
+ lydict_remove(module->ctx, module_name);
lydict_remove(module->ctx, value);
ret = EXIT_FAILURE;
goto error;
}
+ lydict_remove(module->ctx, module_name);
lydict_remove(module->ctx, value);
if (type->base == LY_TYPE_ERR) {
@@ -1009,10 +1013,6 @@
return EXIT_SUCCESS;
error:
- if (type->module_name) {
- lydict_remove(module->ctx, type->module_name);
- type->module_name = NULL;
- }
if (base) {
type->base = base_tmp;
}
diff --git a/src/parser_yin.c b/src/parser_yin.c
index c3a597b..2712fe1 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -516,7 +516,7 @@
fill_yin_type(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_type *type,
int parenttype, struct unres_schema *unres)
{
- const char *value, *name;
+ const char *value, *name, *module_name = NULL;
struct lys_node *siter;
struct lyxml_elem *next, *next2, *node, *child, exts;
struct lys_restr **restrs, *restr;
@@ -550,10 +550,11 @@
/* module name */
name = value;
if (value[i]) {
- type->module_name = lydict_insert(module->ctx, value, i);
+ module_name = lydict_insert(module->ctx, value, i);
name += i;
if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
+ lydict_remove(module->ctx, module_name);
lydict_remove(module->ctx, value);
goto error;
}
@@ -561,19 +562,22 @@
++name;
}
- rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
+ rc = resolve_superior_type(name, module_name, module, parent, &type->der);
if (rc == -1) {
- LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
+ LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, module_name);
+ lydict_remove(module->ctx, module_name);
lydict_remove(module->ctx, value);
goto error;
/* the type could not be resolved or it was resolved to an unresolved typedef */
} else if (rc == EXIT_FAILURE) {
LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
+ lydict_remove(module->ctx, module_name);
lydict_remove(module->ctx, value);
ret = EXIT_FAILURE;
goto error;
}
+ lydict_remove(module->ctx, module_name);
lydict_remove(module->ctx, value);
if (type->base == LY_TYPE_ERR) {
@@ -1541,10 +1545,6 @@
return EXIT_SUCCESS;
error:
- if (type->module_name) {
- lydict_remove(module->ctx, type->module_name);
- type->module_name = NULL;
- }
lyxml_free_withsiblings(module->ctx, exts.child);
return ret;
diff --git a/src/printer.c b/src/printer.c
index f04e3f5..674b3ae 100644
--- a/src/printer.c
+++ b/src/printer.c
@@ -169,7 +169,7 @@
}
static int
-write_iff(struct lyout *out, const struct lys_module *module, struct lys_iffeature *expr, int module_name_or_prefix,
+write_iff(struct lyout *out, const struct lys_module *module, struct lys_iffeature *expr, int prefix_kind,
int *index_e, int *index_f)
{
int count = 0, brackets_flag = *index_e;
@@ -181,10 +181,13 @@
switch (op) {
case LYS_IFF_F:
if (lys_main_module(expr->features[*index_f]->module) != lys_main_module(module)) {
- if (module_name_or_prefix) {
+ if (prefix_kind == 0) {
+ count += ly_print(out, "%s:", transform_module_name2import_prefix(module,
+ lys_main_module(expr->features[*index_f]->module)->name));
+ } else if (prefix_kind == 1) {
count += ly_print(out, "%s:", lys_main_module(expr->features[*index_f]->module)->name);
- } else {
- count += ly_print(out, "%s:", transform_module_name2import_prefix(module, lys_main_module(expr->features[*index_f]->module)->name));
+ } else if (prefix_kind == 2) {
+ count += ly_print(out, "%s:", lys_main_module(expr->features[*index_f]->module)->prefix);
}
}
count += ly_print(out, expr->features[*index_f]->name);
@@ -192,7 +195,7 @@
break;
case LYS_IFF_NOT:
count += ly_print(out, "not ");
- count += write_iff(out, module, expr, module_name_or_prefix, index_e, index_f);
+ count += write_iff(out, module, expr, prefix_kind, index_e, index_f);
break;
case LYS_IFF_AND:
if (brackets_flag) {
@@ -206,9 +209,9 @@
if (brackets_flag) {
count += ly_print(out, "(");
}
- count += write_iff(out, module, expr, module_name_or_prefix, index_e, index_f);
+ count += write_iff(out, module, expr, prefix_kind, index_e, index_f);
count += ly_print(out, " %s ", op == LYS_IFF_OR ? "or" : "and");
- count += write_iff(out, module, expr, module_name_or_prefix, index_e, index_f);
+ count += write_iff(out, module, expr, prefix_kind, index_e, index_f);
if (brackets_flag) {
count += ly_print(out, ")");
}
@@ -218,22 +221,22 @@
}
int
-ly_print_iffeature(struct lyout *out, const struct lys_module *module, struct lys_iffeature *expr, int module_name_or_prefix)
+ly_print_iffeature(struct lyout *out, const struct lys_module *module, struct lys_iffeature *expr, int prefix_kind)
{
int index_e = 0, index_f = 0;
if (expr->expr) {
- return write_iff(out, module, expr, module_name_or_prefix, &index_e, &index_f);
+ return write_iff(out, module, expr, prefix_kind, &index_e, &index_f);
}
return 0;
}
static int
-lys_print_(struct lyout *out, const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node)
+lys_print_(struct lyout *out, const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node,
+ int line_length, int options)
{
int ret;
- int grps = 0;
switch (format) {
case LYS_OUT_YIN:
@@ -246,11 +249,8 @@
ret = yang_print_model(out, module);
lys_switch_deviations((struct lys_module *)module);
break;
- case LYS_OUT_TREE_GRPS:
- grps = 1;
- /* falls through */
case LYS_OUT_TREE:
- ret = tree_print_model(out, module, grps);
+ ret = tree_print_model(out, module, target_node, line_length, options);
break;
case LYS_OUT_INFO:
ret = info_print_model(out, module, target_node);
@@ -265,7 +265,8 @@
}
API int
-lys_print_file(FILE *f, const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node)
+lys_print_file(FILE *f, const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node,
+ int line_length, int options)
{
struct lyout out;
@@ -277,11 +278,12 @@
out.type = LYOUT_STREAM;
out.method.f = f;
- return lys_print_(&out, module, format, target_node);
+ return lys_print_(&out, module, format, target_node, line_length, options);
}
API int
-lys_print_fd(int fd, const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node)
+lys_print_fd(int fd, const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node,
+ int line_length, int options)
{
struct lyout out;
@@ -293,11 +295,12 @@
out.type = LYOUT_FD;
out.method.fd = fd;
- return lys_print_(&out, module, format, target_node);
+ return lys_print_(&out, module, format, target_node, line_length, options);
}
API int
-lys_print_mem(char **strp, const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node)
+lys_print_mem(char **strp, const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node,
+ int line_length, int options)
{
struct lyout out;
int r;
@@ -312,14 +315,15 @@
out.method.mem.len = 0;
out.method.mem.size = 0;
- r = lys_print_(&out, module, format, target_node);
+ r = lys_print_(&out, module, format, target_node, line_length, options);
*strp = out.method.mem.buf;
return r;
}
API int
-lys_print_clb(ssize_t (*writeclb)(void *arg, const void *buf, size_t count), void *arg, const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node)
+lys_print_clb(ssize_t (*writeclb)(void *arg, const void *buf, size_t count), void *arg, const struct lys_module *module,
+ LYS_OUTFORMAT format, const char *target_node, int line_length, int options)
{
struct lyout out;
@@ -332,7 +336,7 @@
out.method.clb.f = writeclb;
out.method.clb.arg = arg;
- return lys_print_(&out, module, format, target_node);
+ return lys_print_(&out, module, format, target_node, line_length, options);
}
static int
diff --git a/src/printer.h b/src/printer.h
index 331d0af..6f77358 100644
--- a/src/printer.h
+++ b/src/printer.h
@@ -60,13 +60,13 @@
int ly_print(struct lyout *out, const char *format, ...);
void ly_print_flush(struct lyout *out);
int ly_write(struct lyout *out, const char *buf, size_t count);
-/* module_name_or_prefix: 1 - print module names for foreign if-features, 0 - print import prefixes */
-int ly_print_iffeature(struct lyout *out, const struct lys_module *module, struct lys_iffeature *expr, int module_name_or_prefix);
+/* prefix_kind: 0 - print import prefixes for foreign features, 1 - print module names, 2 - print prefixes (tree printer) */
+int ly_print_iffeature(struct lyout *out, const struct lys_module *module, struct lys_iffeature *expr, int prefix_kind);
int yang_print_model(struct lyout *out, const struct lys_module *module);
int yin_print_model(struct lyout *out, const struct lys_module *module);
-int tree_print_model(struct lyout *out, const struct lys_module *module, int groupings);
-int info_print_model(struct lyout *out, const struct lys_module *module, const char *target_node);
+int tree_print_model(struct lyout *out, const struct lys_module *module, const char *target_schema_path, int line_length, int options);
+int info_print_model(struct lyout *out, const struct lys_module *module, const char *target_schema_path);
int json_print_data(struct lyout *out, const struct lyd_node *root, int options);
int xml_print_data(struct lyout *out, const struct lyd_node *root, int options);
diff --git a/src/printer_info.c b/src/printer_info.c
index a9d4234..71d1fae 100644
--- a/src/printer_info.c
+++ b/src/printer_info.c
@@ -403,8 +403,8 @@
}
ly_print(out, "%-*s", INDENT_LEN, "Superior: ");
if (type->der) {
- if (type->module_name) {
- ly_print(out, "%s:", type->module_name);
+ if (!lys_type_is_local(type)) {
+ ly_print(out, "%s:", type->der->module->name);
}
ly_print(out, "%s\n", type->der->name);
} else {
@@ -1004,7 +1004,7 @@
}
int
-info_print_model(struct lyout *out, const struct lys_module *module, const char *target_node)
+info_print_model(struct lyout *out, const struct lys_module *module, const char *target_schema_path)
{
int i, rc;
char *spec_target = NULL;
@@ -1012,45 +1012,45 @@
struct lys_tpdf *tpdf = NULL;
uint8_t tpdf_size = 0;
- if (!target_node) {
+ if (!target_schema_path) {
if (module->type == 0) {
info_print_module(out, module);
} else {
info_print_submodule(out, (struct lys_submodule *)module);
}
} else {
- if ((target_node[0] == '/') || !strncmp(target_node, "type/", 5)) {
- rc = resolve_absolute_schema_nodeid((target_node[0] == '/' ? target_node : target_node + 4), module,
+ if ((target_schema_path[0] == '/') || !strncmp(target_schema_path, "type/", 5)) {
+ rc = resolve_absolute_schema_nodeid((target_schema_path[0] == '/' ? target_schema_path : target_schema_path + 4), module,
LYS_ANY & ~(LYS_USES | LYS_AUGMENT | LYS_GROUPING), (const struct lys_node **)&target);
if (rc || !target) {
- ly_print(out, "Target %s could not be resolved.\n", (target_node[0] == '/' ? target_node : target_node + 4));
+ ly_print(out, "Target %s could not be resolved.\n", (target_schema_path[0] == '/' ? target_schema_path : target_schema_path + 4));
return EXIT_FAILURE;
}
- } else if (!strncmp(target_node, "grouping/", 9)) {
+ } else if (!strncmp(target_schema_path, "grouping/", 9)) {
/* cut the data part off */
- if ((spec_target = strchr(target_node + 9, '/'))) {
+ if ((spec_target = strchr(target_schema_path + 9, '/'))) {
/* HACK only temporary */
spec_target[0] = '\0';
++spec_target;
}
- rc = resolve_absolute_schema_nodeid(target_node + 8, module, LYS_GROUPING, (const struct lys_node **)&target);
+ rc = resolve_absolute_schema_nodeid(target_schema_path + 8, module, LYS_GROUPING, (const struct lys_node **)&target);
if (rc || !target) {
- ly_print(out, "Grouping %s not found.\n", target_node + 8);
+ ly_print(out, "Grouping %s not found.\n", target_schema_path + 8);
return EXIT_FAILURE;
}
- } else if (!strncmp(target_node, "typedef/", 8)) {
- if ((spec_target = strrchr(target_node + 8, '/'))) {
+ } else if (!strncmp(target_schema_path, "typedef/", 8)) {
+ if ((spec_target = strrchr(target_schema_path + 8, '/'))) {
/* schema node typedef */
/* HACK only temporary */
spec_target[0] = '\0';
++spec_target;
- rc = resolve_absolute_schema_nodeid(target_node + 7, module,
+ rc = resolve_absolute_schema_nodeid(target_schema_path + 7, module,
LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC | LYS_ACTION,
(const struct lys_node **)&target);
if (rc || !target) {
/* perhaps it's in a grouping */
- rc = resolve_absolute_schema_nodeid(target_node + 7, module, LYS_GROUPING,
+ rc = resolve_absolute_schema_nodeid(target_schema_path + 7, module, LYS_GROUPING,
(const struct lys_node **)&target);
}
if (!rc && target) {
@@ -1083,7 +1083,7 @@
}
} else {
/* module typedef */
- spec_target = (char *)target_node + 8;
+ spec_target = (char *)target_schema_path + 8;
tpdf = module->tpdf;
tpdf_size = module->tpdf_size;
}
@@ -1099,35 +1099,35 @@
spec_target[0] = '/';
if (i == tpdf_size) {
- ly_print(out, "Typedef %s not found.\n", target_node);
+ ly_print(out, "Typedef %s not found.\n", target_schema_path);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
- } else if (!strncmp(target_node, "identity/", 9)) {
- target_node += 9;
+ } else if (!strncmp(target_schema_path, "identity/", 9)) {
+ target_schema_path += 9;
for (i = 0; i < (signed)module->ident_size; ++i) {
- if (!strcmp(module->ident[i].name, target_node)) {
+ if (!strcmp(module->ident[i].name, target_schema_path)) {
break;
}
}
if (i == (signed)module->ident_size) {
- ly_print(out, "Identity %s not found.\n", target_node);
+ ly_print(out, "Identity %s not found.\n", target_schema_path);
return EXIT_FAILURE;
}
info_print_ident_detail(out, &module->ident[i]);
return EXIT_SUCCESS;
- } else if (!strncmp(target_node, "feature/", 8)) {
- target_node += 8;
+ } else if (!strncmp(target_schema_path, "feature/", 8)) {
+ target_schema_path += 8;
for (i = 0; i < module->features_size; ++i) {
- if (!strcmp(module->features[i].name, target_node)) {
+ if (!strcmp(module->features[i].name, target_schema_path)) {
break;
}
}
if (i == module->features_size) {
- ly_print(out, "Feature %s not found.\n", target_node);
+ ly_print(out, "Feature %s not found.\n", target_schema_path);
return EXIT_FAILURE;
}
@@ -1138,14 +1138,14 @@
return EXIT_FAILURE;
}
- if (!strncmp(target_node, "type/", 5)) {
+ if (!strncmp(target_schema_path, "type/", 5)) {
if (!(target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
ly_print(out, "Target is not a leaf or a leaf-list.\n");
return EXIT_FAILURE;
}
info_print_type_detail(out, &((struct lys_node_leaf *)target)->type, 0);
return EXIT_SUCCESS;
- } else if (!strncmp(target_node, "grouping/", 9) && !spec_target) {
+ } else if (!strncmp(target_schema_path, "grouping/", 9) && !spec_target) {
info_print_grouping(out, target);
return EXIT_SUCCESS;
}
@@ -1155,7 +1155,7 @@
rc = resolve_descendant_schema_nodeid(spec_target, target->child, LYS_NO_RPC_NOTIF_NODE,
0, (const struct lys_node **)&target);
if (rc || !target) {
- ly_print(out, "Grouping %s child \"%s\" not found.\n", target_node + 9, spec_target);
+ ly_print(out, "Grouping %s child \"%s\" not found.\n", target_schema_path + 9, spec_target);
return EXIT_FAILURE;
}
/* HACK return previous hack */
diff --git a/src/printer_tree.c b/src/printer_tree.c
index 9d0355b..f8ddaa9 100644
--- a/src/printer_tree.c
+++ b/src/printer_tree.c
@@ -21,29 +21,57 @@
#include "printer.h"
#include "tree_schema.h"
-/* spec_config = 0 (no special config status), 1 (read-only - rpc output, notification), 2 (write-only - rpc input) */
-static void tree_print_snode(struct lyout *out, const struct lys_module *module, int level, uint64_t indent,
- unsigned int max_name_len, const struct lys_node *node, int mask, int spec_config,
- struct lys_node *aug_parent);
+/* module: <name>
+ * <X>+--rw <node-name> */
+#define LY_TREE_MOD_DATA_INDENT 2
-static void
-print_indent(struct lyout *out, uint64_t indent, int level)
+/* <^>rpcs:
+ * <X>+---x <rpc-name> */
+#define LY_TREE_OP_DATA_INDENT 4
+
+/* +--rw leaf<X>string */
+#define LY_TREE_TYPE_INDENT 3
+
+/* +--rw leaf
+ * | <X>string */
+#define LY_TREE_WRAP_INDENT 2
+
+/* these options are mostly inherited in recursive print, non-recursive options are parameters */
+typedef struct {
+ const struct lys_module *module; /**< (sub)module we are printing from */
+ uint8_t base_indent; /**< base indent size of all the printed text */
+ uint64_t indent; /**< bit-field of sibling (1)/ no sibling(0) on corresponding depths */
+ uint16_t line_length; /**< maximum desired line length */
+ int spec_config; /**< special config flags - 0 (no special config status),
+ 1 (read-only - rpc output, notification), 2 (write-only - rpc input) */
+ int options; /**< user-specified tree printer options */
+} tp_opts;
+
+static void tree_print_snode(struct lyout *out, int level, uint16_t max_name_len, const struct lys_node *node, int mask,
+ const struct lys_node *aug_parent, int subtree, tp_opts *opts);
+
+static int
+tree_print_indent(struct lyout *out, int level, tp_opts *opts)
{
- int i;
+ int i, ret = 0;
- ly_print(out, " ");
- for (i = 1; i < level; ++i) {
- if (indent & (1 << i)) {
- ly_print(out, "| ");
+ if (opts->base_indent) {
+ ret += ly_print(out, "%*s", opts->base_indent, " ");
+ }
+ for (i = 0; i < level; ++i) {
+ if (opts->indent & (1 << i)) {
+ ret += ly_print(out, "| ");
} else {
- ly_print(out, " ");
+ ret += ly_print(out, " ");
}
}
+
+ return ret;
}
static int
-sibling_is_valid_child(const struct lys_node *node, int including, const struct lys_module *sub_module,
- struct lys_node *aug_parent, LYS_NODE nodetype)
+tree_sibling_is_valid_child(const struct lys_node *node, int including, const struct lys_module *module,
+ const struct lys_node *aug_parent, LYS_NODE nodetype)
{
struct lys_node *cur, *cur2;
@@ -60,21 +88,21 @@
return 0;
}
- if (sub_module->type && (lys_main_module(sub_module) != lys_node_module(cur))) {
+ if (module->type && (lys_main_module(module) != lys_node_module(cur))) {
continue;
}
if (!lys_is_disabled(cur, 0)) {
if (cur->nodetype == LYS_USES) {
- if (sibling_is_valid_child(cur->child, 1, sub_module, NULL, nodetype)) {
+ if (tree_sibling_is_valid_child(cur->child, 1, module, NULL, nodetype)) {
return 1;
}
} else {
switch (nodetype) {
case LYS_GROUPING:
- /* we are printing groupings, find another */
+ /* we are printing groupings, they are printer separately */
if (cur->nodetype == LYS_GROUPING) {
- return 1;
+ return 0;
}
break;
case LYS_RPC:
@@ -110,25 +138,24 @@
/* if in uses, the following printed child can actually be in the parent node :-/ */
if (lys_parent(node) && (lys_parent(node)->nodetype == LYS_USES)) {
- return sibling_is_valid_child(lys_parent(node), 0, sub_module, NULL, nodetype);
+ return tree_sibling_is_valid_child(lys_parent(node), 0, module, NULL, nodetype);
}
return 0;
}
-uint64_t
-create_indent(int level, uint64_t old_indent, const struct lys_node *node, const struct lys_module *sub_module,
- struct lys_node *aug_parent)
+static void
+tree_next_indent(int level, const struct lys_node *node, const struct lys_node *aug_parent, tp_opts *opts)
{
- uint64_t new_indent;
int next_is_case = 0, has_next = 0;
if (level > 64) {
LOGINT;
- return 0;
+ return;
}
- new_indent = old_indent;
+ /* clear level indent (it may have been set for some line wrapping) */
+ opts->indent &= ~(uint64_t)(1 << (level - 1));
/* this is the direct child of a case */
if ((node->nodetype != LYS_CASE) && lys_parent(node) && (lys_parent(node)->nodetype & (LYS_CASE | LYS_CHOICE))) {
@@ -139,604 +166,749 @@
}
/* next is a node that will actually be printed */
- has_next = sibling_is_valid_child(node, 0, sub_module, aug_parent, node->nodetype);
+ has_next = tree_sibling_is_valid_child(node, 0, opts->module, aug_parent, node->nodetype);
+ /* set level indent */
if (has_next && !next_is_case) {
- new_indent |= (uint64_t)1 << (level - 1);
+ opts->indent |= (uint64_t)1 << (level - 1);
}
-
- return new_indent;
}
-static unsigned int
-get_max_name_len(const struct lys_module *module, const struct lys_node *node)
+static uint16_t
+tree_get_max_name_len(const struct lys_node *sibling, const struct lys_node *aug_parent, int type_mask,
+ tp_opts *opts)
{
const struct lys_node *sub;
- struct lys_module *mod;
- unsigned int max_name_len = 0, uses_max_name_len, name_len;
+ struct lys_module *nodemod;
+ unsigned int max_name_len = 0, name_len;
- LY_TREE_FOR(node, sub) {
- if (module->type && (sub->module != module)) {
+ LY_TREE_FOR(sibling, sub) {
+ if (opts->module->type && (sub->module != opts->module)) {
/* when printing submodule, we are only concerned with its own data (they are in the module data) */
continue;
}
+ if (aug_parent && (sub->parent != aug_parent)) {
+ /* when printing augment children, skip other target children */
+ continue;
+ }
+ if (!(sub->nodetype & type_mask)) {
+ /* this sibling will not be printed */
+ continue;
+ }
- if (sub->nodetype == LYS_USES) {
- uses_max_name_len = get_max_name_len(module, sub->child);
- if (uses_max_name_len > max_name_len) {
- max_name_len = uses_max_name_len;
+ if ((sub->nodetype == LYS_USES) && !(opts->options & LYS_OUTOPT_TREE_USES)) {
+ name_len = tree_get_max_name_len(sub->child, NULL, type_mask, opts);
+ } else {
+ nodemod = lys_node_module(sub);
+ name_len = strlen(sub->name);
+ if (lys_main_module(opts->module) != nodemod) {
+ /* ":" */
+ ++name_len;
+ if (opts->options & LYS_OUTOPT_TREE_RFC) {
+ name_len += strlen(nodemod->prefix);
+ } else {
+ name_len += strlen(nodemod->name);
+ }
}
- } else if (sub->nodetype &
- (LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA | LYS_CASE)) {
- mod = lys_node_module(sub);
- name_len = strlen(sub->name) + (module == mod ? 0 : strlen(mod->name) + 1);
- if (name_len > max_name_len) {
- max_name_len = name_len;
+
+ /* add characters for optional opts */
+ switch (sub->nodetype) {
+ case LYS_LEAF:
+ case LYS_LEAFLIST:
+ case LYS_LIST:
+ case LYS_ANYDATA:
+ case LYS_ANYXML:
+ case LYS_CONTAINER:
+ case LYS_CASE:
+ ++name_len;
+ break;
+ case LYS_CHOICE:
+ /* choice is longer :-/ */
+ name_len += 2;
+ if (!(sub->flags & LYS_MAND_TRUE)) {
+ ++name_len;
+ }
+ break;
+ default:
+ break;
}
}
+
+ if (name_len > max_name_len) {
+ max_name_len = name_len;
+ }
}
return max_name_len;
}
-static void
-tree_print_type(struct lyout *out, const struct lys_type *type)
+static int
+tree_leaf_is_mandatory(const struct lys_node *node)
{
- if ((type->base == LY_TYPE_LEAFREF) && !type->der->module) {
- ly_print(out, "-> %s", type->info.lref.path);
- } else if (type->module_name) {
- ly_print(out, "%s:%s", type->module_name, type->der->name);
- } else {
- ly_print(out, "%s", type->der->name);
- }
-}
-
-static void
-tree_print_config(struct lyout *out, const struct lys_node *node, int spec_config)
-{
- if (spec_config == 0) {
- ly_print(out, "%s ", (node->flags & LYS_CONFIG_W) ? "rw" : (node->flags & LYS_CONFIG_R) ? "ro" : "--");
- } else if (spec_config == 1) {
- ly_print(out, "-w ");
- } else if (spec_config == 2) {
- ly_print(out, "ro ");
- }
-}
-
-static void
-tree_print_features(struct lyout *out, const struct lys_module *module,
- struct lys_iffeature *iffeature, uint8_t iffeature_size)
-{
- int i;
-
- if (!iffeature_size) {
- return;
- }
-
- ly_print(out, " {");
- for (i = 0; i < iffeature_size; i++) {
- if (i > 0) {
- ly_print(out, ",");
- }
- ly_print_iffeature(out, module, &iffeature[i], 1);
- }
- ly_print(out, "}?");
-}
-
-static void
-tree_print_inout(struct lyout *out, const struct lys_module *module, int level, uint64_t indent,
- const struct lys_node *node, int spec_config, struct lys_node *aug_parent)
-{
- unsigned int max_child_len;
- uint64_t new_indent;
- struct lys_node *sub;
-
- assert(spec_config);
-
- if (node->flags & LYS_IMPLICIT) {
- /* implicit input/output which is not a part of the schema */
- return;
- }
-
- print_indent(out, indent, level);
- ly_print(out, "+--%s %s\n", (spec_config == 1 ? "-w" : "ro"), (spec_config == 1 ? "input" : "output"));
-
- level++;
- new_indent = create_indent(level, indent, node, module, aug_parent);
-
- max_child_len = get_max_name_len(module, node->child);
-
- LY_TREE_FOR(node->child, sub) {
- /* submodule, foreign augments */
- if (module->type && (sub->parent != node) && (sub->module != module)) {
- continue;
- }
- tree_print_snode(out, module, level, new_indent, max_child_len, sub,
- LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA | LYS_USES,
- spec_config, NULL);
- }
-}
-
-static void
-tree_print_container(struct lyout *out, const struct lys_module *module, int level, uint64_t indent,
- const struct lys_node *node, int spec_config, struct lys_node *aug_parent)
-{
- unsigned int max_child_len;
- uint64_t new_indent;
- struct lys_node_container *cont = (struct lys_node_container *)node;
- struct lys_node *sub;
- struct lys_module *nodemod;
-
- assert(spec_config >= 0 && spec_config <= 2);
-
- print_indent(out, indent, level);
- ly_print(out, "%s--", (cont->flags & LYS_STATUS_DEPRC ? "x" : (cont->flags & LYS_STATUS_OBSLT ? "o" : "+")));
- tree_print_config(out, node, spec_config);
-
- nodemod = lys_node_module(node);
- if (lys_main_module(module) != nodemod) {
- ly_print(out, "%s:", nodemod->name);
- }
-
- ly_print(out, "%s%s", cont->name, (cont->presence ? "!" : ""));
-
- tree_print_features(out, module, cont->iffeature, cont->iffeature_size);
-
- ly_print(out, "\n");
-
- level++;
- new_indent = create_indent(level, indent, node, module, aug_parent);
-
- max_child_len = get_max_name_len(module, node->child);
-
- LY_TREE_FOR(node->child, sub) {
- /* submodule, foreign augments */
- if (module->type && (sub->parent != node) && (sub->module != module)) {
- continue;
- }
- tree_print_snode(out, module, level, new_indent, max_child_len, sub,
- LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA | LYS_USES | LYS_ACTION,
- spec_config, NULL);
- }
-}
-
-static void
-tree_print_choice(struct lyout *out, const struct lys_module *module, int level, uint64_t indent,
- const struct lys_node *node, int spec_config, struct lys_node *aug_parent)
-{
- unsigned int max_child_len;
- uint64_t new_indent;
- struct lys_node_choice *choice = (struct lys_node_choice *)node;
- struct lys_node *sub;
- struct lys_module *nodemod;
-
- assert(spec_config >= 0 && spec_config <= 2);
-
- print_indent(out, indent, level);
- ly_print(out, "%s--", (choice->flags & LYS_STATUS_DEPRC ? "x" : (choice->flags & LYS_STATUS_OBSLT ? "o" : "+")));
- tree_print_config(out, node, spec_config);
-
- ly_print(out, "(");
-
- nodemod = lys_node_module(node);
- if (lys_main_module(module) != nodemod) {
- ly_print(out, "%s:", nodemod->name);
- }
-
- ly_print(out, "%s)%s", choice->name, (choice->flags & LYS_MAND_TRUE ? "" : "?"));
-
- if (choice->dflt != NULL) {
- ly_print(out, " <%s>", choice->dflt->name);
- }
-
- tree_print_features(out, module, choice->iffeature, choice->iffeature_size);
-
- ly_print(out, "\n");
-
- level++;
- new_indent = create_indent(level, indent, node, module, aug_parent);
-
- max_child_len = get_max_name_len(module, node->child);
-
- LY_TREE_FOR(node->child, sub) {
- /* submodule, foreign augments */
- if (module->type && (sub->parent != node) && (sub->module != module)) {
- continue;
- }
- tree_print_snode(out, module, level, new_indent, max_child_len, sub,
- LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA,
- spec_config, NULL);
- }
-}
-
-static void
-tree_print_case(struct lyout *out, const struct lys_module *module, int level, uint64_t indent,
- unsigned int max_name_len, const struct lys_node *node, int spec_config, struct lys_node *aug_parent)
-{
- uint64_t new_indent;
- struct lys_node_case *cas = (struct lys_node_case *)node;
- struct lys_node *sub;
- struct lys_module *nodemod;
-
- print_indent(out, indent, level);
- ly_print(out, "%s--:(", (cas->flags & LYS_STATUS_DEPRC ? "x" : (cas->flags & LYS_STATUS_OBSLT ? "o" : "+")));
-
- nodemod = lys_node_module(node);
- if (lys_main_module(module) != nodemod) {
- ly_print(out, "%s:", nodemod->name);
- }
-
- ly_print(out, "%s)", cas->name);
-
- tree_print_features(out, module, cas->iffeature, cas->iffeature_size);
-
- ly_print(out, "\n");
-
- level++;
- new_indent = create_indent(level, indent, node, module, aug_parent);
-
- LY_TREE_FOR(node->child, sub) {
- /* submodule, foreign augments */
- if (module->type && (sub->parent != node) && (sub->module != module)) {
- continue;
- }
- tree_print_snode(out, module, level, new_indent, max_name_len, sub,
- LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA | LYS_USES,
- spec_config, NULL);
- }
-}
-
-static void
-tree_print_anydata(struct lyout *out, const struct lys_module *module, int level, uint64_t indent,
- unsigned int max_name_len, const struct lys_node *node, int spec_config)
-{
- uint8_t prefix_len;
- struct lys_module *nodemod;
- struct lys_node_anydata *any = (struct lys_node_anydata *)node;
-
- assert(spec_config >= 0 && spec_config <= 2);
-
- print_indent(out, indent, level);
- ly_print(out, "%s--", (any->flags & LYS_STATUS_DEPRC ? "x" : (any->flags & LYS_STATUS_OBSLT ? "o" : "+")));
- tree_print_config(out, node, spec_config);
-
- prefix_len = 0;
- nodemod = lys_node_module(node);
- if (lys_main_module(module) != nodemod) {
- ly_print(out, "%s:", nodemod->name);
- prefix_len = strlen(nodemod->name)+1;
- }
-
- ly_print(out, "%s%s%*s%s", any->name, (any->flags & LYS_MAND_TRUE ? " " : "?"),
- 3 + (int)((max_name_len - strlen(any->name)) - prefix_len), " ",
- any->nodetype == LYS_ANYXML ? "anyxml" : "anydata");
-
- tree_print_features(out, module, any->iffeature, any->iffeature_size);
-
- ly_print(out, "\n");
-}
-
-static void
-tree_print_leaf(struct lyout *out, const struct lys_module *module, int level, uint64_t indent,
- unsigned int max_name_len, const struct lys_node *node, int spec_config)
-{
- uint8_t prefix_len;
- struct lys_node_leaf *leaf = (struct lys_node_leaf *)node;
- struct lys_node *parent;
+ const struct lys_node *parent;
struct lys_node_list *list;
- struct lys_module *nodemod;
- int i, is_key = 0;
+ uint16_t i;
- assert(spec_config >= 0 && spec_config <= 2);
-
- /* get know if the leaf is a key in a list, in that case it is
- * mandatory by default */
for (parent = lys_parent(node); parent && parent->nodetype == LYS_USES; parent = lys_parent(parent));
if (parent && parent->nodetype == LYS_LIST) {
list = (struct lys_node_list *)parent;
for (i = 0; i < list->keys_size; i++) {
- if (list->keys[i] == leaf) {
- is_key = 1;
- break;
+ if (list->keys[i] == (struct lys_node_leaf *)node) {
+ return 1;
}
}
}
- print_indent(out, indent, level);
- ly_print(out, "%s--", (leaf->flags & LYS_STATUS_DEPRC ? "x" : (leaf->flags & LYS_STATUS_OBSLT ? "o" : "+")));
- tree_print_config(out, node, spec_config);
-
- prefix_len = 0;
- nodemod = lys_node_module(node);
- if (lys_main_module(module) != nodemod) {
- ly_print(out, "%s:", nodemod->name);
- prefix_len = strlen(nodemod->name)+1;
- }
-
- ly_print(out, "%s%s%*s", leaf->name, ((leaf->flags & LYS_MAND_TRUE) || is_key ? " " : "?"),
- 3 + (int)((max_name_len - strlen(leaf->name)) - prefix_len), " ");
-
- tree_print_type(out, &leaf->type);
-
- if (leaf->dflt) {
- ly_print(out, " <%s>", leaf->dflt);
- }
-
- tree_print_features(out, module, leaf->iffeature, leaf->iffeature_size);
-
- ly_print(out, "\n");
+ return 0;
}
-static void
-tree_print_leaflist(struct lyout *out, const struct lys_module *module, int level, uint64_t indent,
- unsigned int max_name_len, const struct lys_node *node, int spec_config)
+static int
+tree_print_wrap(struct lyout *out, int level, int line_printed, uint8_t indent, uint16_t len, tp_opts *opts)
{
- struct lys_node_leaflist *leaflist = (struct lys_node_leaflist *)node;
- struct lys_module *nodemod;
+ if (opts->line_length && (line_printed + indent + len > opts->line_length)) {
+ ly_print(out, "\n");
+ line_printed = tree_print_indent(out, level, opts);
+ /* 3 for config + space */
+ line_printed += ly_print(out, "%*s", 3 + LY_TREE_WRAP_INDENT, "");
+ } else {
+ line_printed += ly_print(out, "%*s", indent, "");
+ }
- assert(spec_config >= 0 && spec_config <= 2);
+ return line_printed;
+}
- print_indent(out, indent, level);
- ly_print(out, "%s--", (leaflist->flags & LYS_STATUS_DEPRC ? "x" : (leaflist->flags & LYS_STATUS_OBSLT ? "o" : "+")));
- tree_print_config(out, node, spec_config);
+static int
+tree_print_prefix(struct lyout *out, const struct lys_node *node, tp_opts *opts)
+{
+ uint16_t ret = 0;
+ const struct lys_module *nodemod;
nodemod = lys_node_module(node);
- if (lys_main_module(module) != nodemod) {
- ly_print(out, "%s:", nodemod->name);
- }
-
- ly_print(out, "%s*%*s", leaflist->name, 3 + (int)(max_name_len - strlen(leaflist->name)), " ");
-
- tree_print_type(out, &leaflist->type);
-
- tree_print_features(out, module, leaflist->iffeature, leaflist->iffeature_size);
-
- ly_print(out, "\n");
-}
-
-static void
-tree_print_list(struct lyout *out, const struct lys_module *module, int level, uint64_t indent,
- const struct lys_node *node, int spec_config, struct lys_node *aug_parent)
-{
- int i;
- unsigned int max_child_len;
- uint64_t new_indent;
- struct lys_node *sub;
- struct lys_node_list *list = (struct lys_node_list *)node;
- struct lys_module *nodemod;
-
- print_indent(out, indent, level);
- ly_print(out, "%s--", (list->flags & LYS_STATUS_DEPRC ? "x" : (list->flags & LYS_STATUS_OBSLT ? "o" : "+")));
- tree_print_config(out, node, spec_config);
-
- nodemod = lys_node_module(node);
- if (lys_main_module(module) != nodemod) {
- ly_print(out, "%s:", nodemod->name);
- }
-
- ly_print(out, "%s*", list->name);
-
- for (i = 0; i < list->keys_size; i++) {
- if (i == 0) {
- ly_print(out, " [");
+ if (lys_main_module(opts->module) != nodemod) {
+ if (opts->options & LYS_OUTOPT_TREE_RFC) {
+ ret = ly_print(out, "%s:", nodemod->prefix);
+ } else {
+ ret = ly_print(out, "%s:", nodemod->name);
}
- ly_print(out, "%s%s", list->keys[i]->name, i + 1 < list->keys_size ? " " : "]");
}
- tree_print_features(out, module, list->iffeature, list->iffeature_size);
+ return ret;
+}
- ly_print(out, "\n");
+static int
+tree_print_type(struct lyout *out, const struct lys_type *type, int options, const char **out_str)
+{
+ struct lys_module *type_mod = ((struct lys_tpdf *)type->parent)->module;
+ const char *str;
+ char *tmp;
+ int printed;
- level++;
- new_indent = create_indent(level, indent, node, module, aug_parent);
-
- max_child_len = get_max_name_len(module, node->child);
-
- LY_TREE_FOR(node->child, sub) {
- /* submodule, foreign augments */
- if (module->type && (sub->parent != node) && (sub->module != module)) {
- continue;
+ if ((type->base == LY_TYPE_LEAFREF) && !type->der->module) {
+ if (options & LYS_OUTOPT_TREE_NO_LEAFREF) {
+ if (out_str) {
+ printed = 7;
+ *out_str = lydict_insert(type_mod->ctx, "leafref", printed);
+ } else {
+ printed = ly_print(out, "leafref");
+ }
+ } else {
+ if (options & LYS_OUTOPT_TREE_RFC) {
+ str = transform_json2schema(type_mod, type->info.lref.path);
+ if (out_str) {
+ printed = 3 + strlen(str);
+ tmp = malloc(printed + 1);
+ LY_CHECK_ERR_RETURN(!tmp, LOGMEM, 0);
+ sprintf(tmp, "-> %s", str);
+ *out_str = lydict_insert_zc(type_mod->ctx, tmp);
+ } else {
+ printed = ly_print(out, "-> %s", str);
+ }
+ lydict_remove(type_mod->ctx, str);
+ } else {
+ if (out_str) {
+ printed = 3 + strlen(type->info.lref.path);
+ tmp = malloc(printed + 1);
+ LY_CHECK_ERR_RETURN(!tmp, LOGMEM, 0);
+ sprintf(tmp, "-> %s", type->info.lref.path);
+ *out_str = lydict_insert_zc(type_mod->ctx, tmp);
+ } else {
+ printed = ly_print(out, "-> %s", type->info.lref.path);
+ }
+ }
}
- tree_print_snode(out, module, level, new_indent, max_child_len, sub,
- LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ANYDATA | LYS_ACTION,
- spec_config, NULL);
+ } else if (!lys_type_is_local(type)) {
+ if (options & LYS_OUTOPT_TREE_RFC) {
+ str = transform_module_name2import_prefix(type_mod, type->der->module->name);
+ if (out_str) {
+ printed = strlen(str) + 1 + strlen(type->der->name);
+ tmp = malloc(printed + 1);
+ LY_CHECK_ERR_RETURN(!tmp, LOGMEM, 0);
+ sprintf(tmp, "%s:%s", str, type->der->name);
+ *out_str = lydict_insert_zc(type_mod->ctx, tmp);
+ } else {
+ printed = ly_print(out, "%s:%s", str, type->der->name);
+ }
+ } else {
+ if (out_str) {
+ printed = strlen(type->der->module->name) + 1 + strlen(type->der->name);
+ tmp = malloc(printed + 1);
+ LY_CHECK_ERR_RETURN(!tmp, LOGMEM, 0);
+ sprintf(tmp, "%s:%s", type->der->module->name, type->der->name);
+ *out_str = lydict_insert_zc(type_mod->ctx, tmp);
+ } else {
+ printed = ly_print(out, "%s:%s", type->der->module->name, type->der->name);
+ }
+ }
+ } else {
+ if (out_str) {
+ printed = strlen(type->der->name);
+ *out_str = lydict_insert(type_mod->ctx, type->der->name, printed);
+ } else {
+ printed = ly_print(out, "%s", type->der->name);
+ }
}
+
+ return printed;
}
-static void
-tree_print_uses(struct lyout *out, const struct lys_module *module, int level, uint64_t indent, unsigned int max_name_len,
- const struct lys_node *node, int spec_config, struct lys_node *aug_parent)
+static int
+tree_print_config(struct lyout *out, const struct lys_node *node, int spec_config)
{
- struct lys_node *sub;
+ int ret;
- LY_TREE_FOR(node->child, sub) {
- tree_print_snode(out, module, level, indent, max_name_len, sub,
- LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_ANYDATA,
- spec_config, aug_parent);
+ switch (node->nodetype) {
+ case LYS_RPC:
+ case LYS_ACTION:
+ return ly_print(out, "-x ");
+ case LYS_NOTIF:
+ return ly_print(out, "-n ");
+ case LYS_USES:
+ return ly_print(out, "-u ");
+ case LYS_CASE:
+ return ly_print(out, ":(");
+ default:
+ break;
}
+
+ if (spec_config == 0) {
+ ret = ly_print(out, "%s ", (node->flags & LYS_CONFIG_W) ? "rw" : (node->flags & LYS_CONFIG_R) ? "ro" : "--");
+ } else if (spec_config == 1) {
+ ret = ly_print(out, "-w ");
+ } else if (spec_config == 2) {
+ ret = ly_print(out, "ro ");
+ }
+
+ if (node->nodetype == LYS_CHOICE) {
+ ret += ly_print(out, "(");
+ }
+ return ret;
}
-static void
-tree_print_rpc_action(struct lyout *out, const struct lys_module *module, int level, uint64_t indent,
- const struct lys_node *node, struct lys_node *aug_parent)
+static int
+tree_print_features(struct lyout *out, struct lys_iffeature *iff1, uint8_t iff1_size, struct lys_iffeature *iff2,
+ uint8_t iff2_size, tp_opts *opts, const char **out_str)
{
- uint64_t new_indent;
- struct lys_node *sub;
- struct lys_node_rpc_action *rpc = (struct lys_node_rpc_action *)node;
+ int i, printed;
+ struct lyout *o;
- if (lys_is_disabled(node, 0)) {
+ if (!iff1_size && !iff2_size) {
+ return 0;
+ }
+
+ if (out_str) {
+ o = malloc(sizeof *o);
+ LY_CHECK_ERR_RETURN(!o, LOGMEM, 0);
+ o->type = LYOUT_MEMORY;
+ o->method.mem.buf = NULL;
+ o->method.mem.len = 0;
+ o->method.mem.size = 0;
+ } else {
+ o = out;
+ }
+
+ printed = ly_print(o, "{");
+ for (i = 0; i < iff1_size; i++) {
+ if (i > 0) {
+ printed += ly_print(o, ",");
+ }
+ printed += ly_print_iffeature(o, opts->module, &iff1[i], opts->options & LYS_OUTOPT_TREE_RFC ? 2 : 1);
+ }
+ for (i = 0; i < iff2_size; i++) {
+ if (i > 0) {
+ printed += ly_print(o, ",");
+ }
+ printed += ly_print_iffeature(o, opts->module, &iff2[i], opts->options & LYS_OUTOPT_TREE_RFC ? 2 : 1);
+ }
+ printed += ly_print(o, "}?");
+
+ if (out_str) {
+ *out_str = lydict_insert_zc(opts->module->ctx, o->method.mem.buf);
+ free(o);
+ }
+
+ return printed;
+}
+
+static int
+tree_print_keys(struct lyout *out, struct lys_node_leaf **keys, uint8_t keys_size, tp_opts *opts, const char **out_str)
+{
+ int i, printed;
+ struct lyout *o;
+
+ if (!keys_size) {
+ return 0;
+ }
+
+ if (out_str) {
+ o = malloc(sizeof *o);
+ LY_CHECK_ERR_RETURN(!o, LOGMEM, 0);
+ o->type = LYOUT_MEMORY;
+ o->method.mem.buf = NULL;
+ o->method.mem.len = 0;
+ o->method.mem.size = 0;
+ } else {
+ o = out;
+ }
+
+ printed = ly_print(o, "[");
+ for (i = 0; i < keys_size; i++) {
+ printed += ly_print(o, "%s%s", keys[i]->name, i + 1 < keys_size ? " " : "]");
+ }
+
+ if (out_str) {
+ *out_str = lydict_insert_zc(opts->module->ctx, o->method.mem.buf);
+ free(o);
+ }
+
+ return printed;
+}
+
+/**
+ * @brief Print schema node in YANG tree diagram formatting.
+ *
+ * @param[in] out libyang output.
+ * @param[in] level Current level of depth.
+ * @param[in] max_name_len Maximal name length of all the siblings (relevant only for nodes with type).
+ * @param[in] node Schema node to print.
+ * @param[in] mask Type mask of children nodes to be printed.
+ * @param[in] aug_parent Augment node parent in case we are printing its direct children.
+ * @param[in] opts Tree printer options structure.
+ */
+static void
+tree_print_snode(struct lyout *out, int level, uint16_t max_name_len, const struct lys_node *node, int mask,
+ const struct lys_node *aug_parent, int subtree, tp_opts *opts)
+{
+ struct lys_node *sub;
+ int line_len, node_len, child_mask;
+ uint8_t text_len, text_indent;
+ uint16_t max_child_len;
+ const char *text_str;
+
+ /* disabled/not printed node */
+ if (lys_is_disabled(node, (node->parent && node->parent->nodetype == LYS_AUGMENT) ? 1 : 0) || !(node->nodetype & mask)) {
return;
}
- print_indent(out, indent, level);
- ly_print(out, "%s---x %s", (rpc->flags & LYS_STATUS_DEPRC ? "x" : (rpc->flags & LYS_STATUS_OBSLT ? "o" : "+")), rpc->name);
-
- tree_print_features(out, module, rpc->iffeature, rpc->iffeature_size);
-
- ly_print(out, "\n");
-
- level++;
- new_indent = create_indent(level, indent, node, module, aug_parent);
-
- LY_TREE_FOR(node->child, sub) {
- /* submodule, foreign augments */
- if (module->type && (sub->parent != node) && (sub->module != module)) {
- continue;
- }
- if (sub->nodetype == LYS_INPUT) {
- tree_print_inout(out, module, level, new_indent, sub, 1, aug_parent);
- } else if (sub->nodetype == LYS_OUTPUT) {
- tree_print_inout(out, module, level, new_indent, sub, 2, aug_parent);
- }
- }
-}
-
-static void
-tree_print_notif(struct lyout *out, const struct lys_module *module, int level, uint64_t indent,
- const struct lys_node *node, struct lys_node *aug_parent)
-{
- unsigned int max_child_len;
- uint64_t new_indent;
- struct lys_node *sub;
- struct lys_node_notif *notif = (struct lys_node_notif *)node;
-
- if (lys_is_disabled(node, 0)) {
+ /* implicit input/output */
+ if (((node->nodetype & mask) & (LYS_INPUT | LYS_OUTPUT)) && (node->flags & LYS_IMPLICIT)) {
return;
}
- print_indent(out, indent, level);
- ly_print(out, "%s---n %s", (notif->flags & LYS_STATUS_DEPRC ? "x" : (notif->flags & LYS_STATUS_OBSLT ? "o" : "+")),
- notif->name);
-
- tree_print_features(out, module, notif->iffeature, notif->iffeature_size);
-
- ly_print(out, "\n");
-
- level++;
- new_indent = create_indent(level, indent, node, module, aug_parent);
-
- max_child_len = get_max_name_len(module, node->child);
-
- LY_TREE_FOR(node->child, sub) {
- /* submodule, foreign augments */
- if (module->type && (sub->parent != node) && (sub->module != module)) {
- continue;
- }
- tree_print_snode(out, module, level, new_indent, max_child_len, sub,
- LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA | LYS_USES, 2, NULL);
- }
-}
-
-static void
-tree_print_grp(struct lyout *out, const struct lys_module *module, int level, uint64_t indent,
- const struct lys_node *node)
-{
- unsigned int max_child_len;
- uint64_t new_indent;
- struct lys_node *sub;
- struct lys_node_grp *grp = (struct lys_node_grp *)node;
-
- if (lys_is_disabled(node, 0)) {
- return;
- }
-
- print_indent(out, indent, level);
- ly_print(out, "%s---- %s", (grp->flags & LYS_STATUS_DEPRC ? "x" : (grp->flags & LYS_STATUS_OBSLT ? "o" : "+")),
- grp->name);
-
- tree_print_features(out, module, grp->iffeature, grp->iffeature_size);
-
- ly_print(out, "\n");
-
- level++;
- new_indent = create_indent(level, indent, node, module, NULL);
-
- max_child_len = get_max_name_len(module, node->child);
-
- LY_TREE_FOR(node->child, sub) {
- /* submodule, foreign augments */
- if (module->type && (sub->parent != node) && (sub->module != module)) {
- continue;
- }
- tree_print_snode(out, module, level, new_indent, max_child_len, sub,
- LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA | LYS_USES, 0, NULL);
- }
-}
-
-/* spec_config = 0 (no special config status), 1 (read-only - rpc output, notification), 2 (write-only - rpc input) */
-static void
-tree_print_snode(struct lyout *out, const struct lys_module *module, int level, uint64_t indent,
- unsigned int max_name_len, const struct lys_node *node, int mask, int spec_config,
- struct lys_node *aug_parent)
-{
- if (lys_is_disabled(node, (node->parent && node->parent->nodetype == LYS_AUGMENT) ? 1 : 0)) {
- return;
- }
-
+ /* special uses and grouping handling */
switch (node->nodetype & mask) {
- case LYS_CONTAINER:
- tree_print_container(out, module, level, indent, node, spec_config, aug_parent);
+ case LYS_USES:
+ if (opts->options & LYS_OUTOPT_TREE_USES) {
+ break;
+ }
+ /* fallthrough */
+ case LYS_GROUPING:
+ goto print_children;
+ default:
break;
- case LYS_CHOICE:
- tree_print_choice(out, module, level, indent, node, spec_config, aug_parent);
- break;
+ }
+
+ /* print indent */
+ line_len = tree_print_indent(out, level, opts);
+ /* print status */
+ line_len += ly_print(out, "%s--", (node->flags & LYS_STATUS_DEPRC ? "x" : (node->flags & LYS_STATUS_OBSLT ? "o" : "+")));
+ /* print config flags (or special opening for case, choice) */
+ line_len += tree_print_config(out, node, opts->spec_config);
+ /* print optionally prefix */
+ node_len = tree_print_prefix(out, node, opts);
+ /* print name */
+ node_len += ly_print(out, node->name);
+
+ /* print one-character opts */
+ switch (node->nodetype & mask) {
case LYS_LEAF:
- tree_print_leaf(out, module, level, indent, max_name_len, node, spec_config);
+ if (!(node->flags & LYS_MAND_TRUE) && !tree_leaf_is_mandatory(node)) {
+ node_len += ly_print(out, "?");
+ }
break;
- case LYS_LEAFLIST:
- tree_print_leaflist(out, module, level, indent, max_name_len, node, spec_config);
+ case LYS_ANYDATA:
+ case LYS_ANYXML:
+ if (!(node->flags & LYS_MAND_TRUE)) {
+ node_len += ly_print(out, "?");
+ }
+ break;
+ case LYS_CONTAINER:
+ if (((struct lys_node_container *)node)->presence) {
+ node_len += ly_print(out, "!");
+ }
break;
case LYS_LIST:
- tree_print_list(out, module, level, indent, node, spec_config, aug_parent);
- break;
- case LYS_ANYXML:
- case LYS_ANYDATA:
- tree_print_anydata(out, module, level, indent, max_name_len, node, spec_config);
- break;
- case LYS_USES:
- tree_print_uses(out, module, level, indent, max_name_len, node, spec_config, aug_parent);
- break;
- case LYS_ACTION:
- tree_print_rpc_action(out, module, level, indent, node, aug_parent);
+ case LYS_LEAFLIST:
+ node_len += ly_print(out, "*");
break;
case LYS_CASE:
- /* a very special case of cases in an augment */
- tree_print_case(out, module, level, indent, max_name_len, node, spec_config, aug_parent);
+ /* kinda shady, but consistent in a way */
+ node_len += ly_print(out, ")");
+ break;
+ case LYS_CHOICE:
+ node_len += ly_print(out, ")");
+ if (!(node->flags & LYS_MAND_TRUE)) {
+ node_len += ly_print(out, "?");
+ }
+ break;
+ default:
+ break;
+ }
+ line_len += node_len;
+
+ /**
+ * wrapped print
+ */
+
+ /* learn next level indent (there is never a sibling for subtree) */
+ ++level;
+ if (!subtree) {
+ tree_next_indent(level, node, aug_parent, opts);
+ }
+
+ /* print type/keys */
+ switch (node->nodetype & mask) {
+ case LYS_LEAF:
+ case LYS_LEAFLIST:
+ assert(max_name_len);
+ text_indent = LY_TREE_TYPE_INDENT + (uint8_t)(max_name_len - node_len);
+ text_len = tree_print_type(out, &((struct lys_node_leaf *)node)->type, opts->options, &text_str);
+ line_len = tree_print_wrap(out, level, line_len, text_indent, text_len, opts);
+ line_len += ly_print(out, text_str);
+ lydict_remove(opts->module->ctx, text_str);
+ break;
+ case LYS_ANYDATA:
+ assert(max_name_len);
+ text_indent = LY_TREE_TYPE_INDENT + (uint8_t)(max_name_len - node_len);
+ line_len = tree_print_wrap(out, level, line_len, text_indent, 7, opts);
+ line_len += ly_print(out, "anydata");
+ break;
+ case LYS_ANYXML:
+ assert(max_name_len);
+ text_indent = LY_TREE_TYPE_INDENT + (uint8_t)(max_name_len - node_len);
+ line_len = tree_print_wrap(out, level, line_len, text_indent, 6, opts);
+ line_len += ly_print(out, "anyxml");
+ break;
+ case LYS_LIST:
+ text_len = tree_print_keys(out, ((struct lys_node_list *)node)->keys, ((struct lys_node_list *)node)->keys_size,
+ opts, &text_str);
+ if (text_len) {
+ line_len = tree_print_wrap(out, level, line_len, 1, text_len, opts);
+ line_len += ly_print(out, text_str);
+ lydict_remove(opts->module->ctx, text_str);
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* print default */
+ if (!(opts->options & LYS_OUTOPT_TREE_RFC)) {
+ switch (node->nodetype & mask) {
+ case LYS_LEAF:
+ text_str = ((struct lys_node_leaf *)node)->dflt;
+ if (text_str) {
+ line_len = tree_print_wrap(out, level, line_len, 1, 2 + strlen(text_str), opts);
+ line_len += ly_print(out, "<%s>", text_str);
+ }
+ break;
+ case LYS_CHOICE:
+ sub = ((struct lys_node_choice *)node)->dflt;
+ if (sub) {
+ line_len = tree_print_wrap(out, level, line_len, 1, 2 + strlen(sub->name), opts);
+ line_len += ly_print(out, "<%s>", sub->name);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* print if-features */
+ switch (node->nodetype & mask) {
+ case LYS_CONTAINER:
+ case LYS_LIST:
+ case LYS_CHOICE:
+ case LYS_CASE:
+ case LYS_ANYDATA:
+ case LYS_ANYXML:
+ case LYS_LEAF:
+ case LYS_LEAFLIST:
+ case LYS_RPC:
+ case LYS_ACTION:
+ case LYS_NOTIF:
+ case LYS_USES:
+ if (node->parent && (node->parent->nodetype == LYS_AUGMENT)) {
+ /* if-features from an augment are de facto inherited */
+ text_len = tree_print_features(out, node->iffeature, node->iffeature_size,
+ node->parent->iffeature, node->parent->iffeature_size, opts, &text_str);
+ } else {
+ text_len = tree_print_features(out, node->iffeature, node->iffeature_size, NULL, 0, opts, &text_str);
+ }
+ if (text_len) {
+ line_len = tree_print_wrap(out, level, line_len, 1, text_len, opts);
+ line_len += ly_print(out, text_str);
+ lydict_remove(opts->module->ctx, text_str);
+ }
+ break;
+ default:
+ /* only grouping */
+ break;
+ }
+
+ /* this node is finished printing */
+ ly_print(out, "\n");
+
+ if ((subtree == 1) || ((node->nodetype & mask) == LYS_USES)) {
+ /* we are printing subtree parents, finish here (or uses option) */
+ return;
+ }
+
+ /* set special config flag */
+ switch (node->nodetype & mask) {
+ case LYS_INPUT:
+ opts->spec_config = 1;
+ break;
+ case LYS_OUTPUT:
+ case LYS_NOTIF:
+ opts->spec_config = 2;
+ break;
+ default:
+ break;
+ }
+
+print_children:
+ /* set child mask and learn the longest child name (needed only if a child can have type) */
+ switch (node->nodetype & mask) {
+ case LYS_LEAF:
+ case LYS_LEAFLIST:
+ case LYS_ANYDATA:
+ case LYS_ANYXML:
+ child_mask = 0;
+ max_child_len = 0;
+ break;
+ case LYS_RPC:
+ case LYS_ACTION:
+ child_mask = LYS_INPUT | LYS_OUTPUT;
+ max_child_len = 0;
+ break;
+ case LYS_CHOICE:
+ child_mask = LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA;
+ max_child_len = tree_get_max_name_len(node->child, NULL, child_mask, opts);
+ break;
+ case LYS_CASE:
+ case LYS_NOTIF:
+ child_mask = LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA | LYS_USES;
+ max_child_len = tree_get_max_name_len(node->child, NULL, child_mask, opts);
+ break;
+ case LYS_INPUT:
+ case LYS_OUTPUT:
+ child_mask = LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA | LYS_USES;
+ max_child_len = tree_get_max_name_len(node->child, NULL, child_mask, opts);
+ break;
+ case LYS_USES:
+ child_mask = LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA | LYS_USES | LYS_ACTION | LYS_NOTIF;
+ /* inherit the name length from the parent, it does not change */
+ max_child_len = max_name_len;
+ break;
+ case LYS_CONTAINER:
+ case LYS_LIST:
+ case LYS_GROUPING:
+ child_mask = LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA | LYS_USES | LYS_ACTION | LYS_NOTIF;
+ max_child_len = tree_get_max_name_len(node->child, NULL, child_mask, opts);
+ break;
+ }
+
+ /* print descendants (children) */
+ if (child_mask) {
+ LY_TREE_FOR(node->child, sub) {
+ /* submodule, foreign augments */
+ if (opts->module->type && (sub->parent != node) && (sub->module != opts->module)) {
+ continue;
+ }
+ tree_print_snode(out, level, max_child_len, sub, child_mask, NULL, 0, opts);
+ }
+ }
+
+ /* reset special config flag */
+ switch (node->nodetype & mask) {
+ case LYS_INPUT:
+ case LYS_OUTPUT:
+ case LYS_NOTIF:
+ opts->spec_config = 0;
break;
default:
break;
}
}
+static void
+tree_print_subtree(struct lyout *out, const struct lys_node *node, tp_opts *opts)
+{
+ unsigned int depth, i, j;
+ int level = 0;
+ const struct lys_node *parent;
+
+ /* learn the depth of the node */
+ depth = 0;
+ parent = node;
+ while (lys_parent(parent)) {
+ if (lys_parent(parent)->nodetype != LYS_USES) {
+ ++depth;
+ }
+ parent = lys_parent(parent);
+ }
+
+ if (parent->nodetype == LYS_RPC) {
+ ly_print(out, "\n%*srpcs:\n", LY_TREE_MOD_DATA_INDENT, "");
+ opts->base_indent = LY_TREE_OP_DATA_INDENT;
+ } else if (parent->nodetype == LYS_NOTIF) {
+ ly_print(out, "\n%*snotifications:\n", LY_TREE_MOD_DATA_INDENT, "");
+ opts->base_indent = LY_TREE_OP_DATA_INDENT;
+ }
+
+ /* print all the parents */
+ if (depth) {
+ i = depth;
+ do {
+ parent = node;
+ for (j = 0; j < i; ++j) {
+ do {
+ parent = lys_parent(parent);
+ } while (parent->nodetype == LYS_USES);
+ }
+
+ tree_print_snode(out, level, 0, parent, LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC | LYS_ACTION
+ | LYS_INPUT | LYS_OUTPUT, NULL, 1, opts);
+
+ ++level;
+ --i;
+ } while (i);
+ }
+
+ /* print the node and its descendants */
+ tree_print_snode(out, level, 0, node, LYS_ANY, NULL, 2, opts);
+}
+
+static int
+tree_print_aug_target(struct lyout *out, int line_printed, uint8_t indent, const char *path, tp_opts *opts)
+{
+ int printed, is_last, len;
+ const char *cur, *next;
+
+ printed = line_printed;
+ cur = path;
+ do {
+ next = strchr(cur + 1, '/');
+ if (!next) {
+ len = strlen(cur) + 1;
+ is_last = 1;
+ } else {
+ len = next - cur;
+ is_last = 0;
+ }
+
+ if (opts->line_length && cur != path && (printed + len > opts->line_length)) {
+ /* line_printed is treated as the base indent */
+ printed = ly_print(out, "\n%*s", line_printed + indent, "");
+ /* minus the newline */
+ --printed;
+ }
+ printed += ly_print(out, "%.*s%s", len, cur, is_last ? ":" : "");
+
+ cur = next;
+ } while (!is_last);
+
+ return printed;
+}
+
int
-tree_print_model(struct lyout *out, const struct lys_module *module, int printgroupings)
+tree_print_model(struct lyout *out, const struct lys_module *module, const char *target_schema_path,
+ int ll, int options)
{
struct lys_node *node, *data;
- unsigned int max_child_len;
- int level = 1, have_rpcs = 0, have_notifs = 0, have_grps = 0;
- uint64_t indent = 0;
- int i;
+ struct ly_set *set;
+ uint16_t max_child_len;
+ int have_rpcs = 0, have_notifs = 0, have_grps = 0, have_augs = 0, printed;
+ const char *str;
+ int i, mask;
+ tp_opts opts;
+
+ memset(&opts, 0, sizeof opts);
+ opts.module = module;
+ opts.line_length = ll;
+ opts.options = options;
+
+ /* we are printing only a subtree */
+ if (target_schema_path) {
+ set = lys_find_path(module, NULL, target_schema_path);
+ if (!set) {
+ return EXIT_FAILURE;
+ } else if (set->number != 1) {
+ LOGVAL(LYE_PATH_INNODE, LY_VLOG_NONE, NULL);
+ if (set->number == 0) {
+ LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "Schema path \"%s\" did not match any nodes.", target_schema_path);
+ } else {
+ LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "Schema path \"%s\" matched more nodes.", target_schema_path);
+ }
+ ly_set_free(set);
+ return EXIT_FAILURE;
+ }
+
+ node = set->set.s[0];
+ ly_set_free(set);
+ }
if (module->type) {
- ly_print(out, "submodule: %s (belongs-to %s)\n", module->name,
- ((struct lys_submodule *)module)->belongsto->name);
+ ly_print(out, "submodule: %s", module->name);
data = ((struct lys_submodule *)module)->belongsto->data;
+ if (options & LYS_OUTOPT_TREE_RFC) {
+ ly_print(out, "\n");
+ } else {
+ ly_print(out, " (belongs-to %s)\n", ((struct lys_submodule *)module)->belongsto->name);
+ }
} else {
ly_print(out, "module: %s\n", module->name);
data = module->data;
}
- /* module */
- max_child_len = get_max_name_len(module, data);
- level++;
+ /* only subtree */
+ if (target_schema_path) {
+ opts.base_indent = LY_TREE_MOD_DATA_INDENT;
+ tree_print_subtree(out, node, &opts);
+ return EXIT_SUCCESS;
+ }
+ /* module */
+ opts.base_indent = LY_TREE_MOD_DATA_INDENT;
+ mask = LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA | LYS_USES;
+ max_child_len = tree_get_max_name_len(data, NULL, mask, &opts);
LY_TREE_FOR(data, node) {
- if (module->type && (node->module != module)) {
+ if (opts.module->type && (node->module != opts.module)) {
/* we're printing the submodule only */
continue;
}
- switch(node->nodetype) {
+ switch (node->nodetype) {
case LYS_RPC:
if (!lys_is_disabled(node, 0)) {
have_rpcs++;
@@ -748,18 +920,20 @@
}
break;
case LYS_GROUPING:
- if (printgroupings && !lys_is_disabled(node, 0)) {
+ if ((options & LYS_OUTOPT_TREE_GROUPING) && !lys_is_disabled(node, 0)) {
have_grps++;
}
break;
default:
- tree_print_snode(out, module, level, indent, max_child_len, node,
- LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA | LYS_USES, 0, NULL);
+ tree_print_snode(out, 0, max_child_len, node, mask, NULL, 0, &opts);
break;
}
}
- /* augment */
+ /* all remaining nodes printed with operation indent */
+ opts.base_indent = LY_TREE_OP_DATA_INDENT;
+
+ /* augments */
for (i = 0; i < module->augment_size; i++) {
if ((module->type && (module->augment[i].target->module == module))
|| (!module->type && (lys_node_module(module->augment[i].target) == module))
@@ -768,44 +942,60 @@
continue;
}
- ly_print(out, "\n augment %s:\n", module->augment[i].target_name);
- LY_TREE_FOR(module->augment[i].child, node) {
+ if (!have_augs) {
+ ly_print(out, "\n");
+ have_augs = 1;
+ }
+
+ printed = ly_print(out, "%*saugment ", LY_TREE_MOD_DATA_INDENT, "");
+ if (options & LYS_OUTOPT_TREE_RFC) {
+ str = transform_json2schema(module, module->augment[i].target_name);
+ tree_print_aug_target(out, printed, LY_TREE_WRAP_INDENT, str, &opts);
+ lydict_remove(module->ctx, str);
+ } else {
+ tree_print_aug_target(out, printed, LY_TREE_WRAP_INDENT, module->augment[i].target_name, &opts);
+ }
+ ly_print(out, "\n");
+
+ data = (struct lys_node *)&module->augment[i];
+ mask = LYS_CHOICE | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA | LYS_USES
+ | LYS_ACTION | LYS_NOTIF;
+ max_child_len = tree_get_max_name_len(data->child, data, mask, &opts);
+ LY_TREE_FOR(data->child, node) {
/* submodule, foreign augments */
- if (node->parent != (struct lys_node *)&module->augment[i]) {
+ if (node->parent != data) {
continue;
}
- tree_print_snode(out, module, level, indent, max_child_len, node,
- LYS_CHOICE | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA | LYS_USES,
- 0, node->parent);
+ tree_print_snode(out, 0, max_child_len, node, mask, data, 0, &opts);
}
}
- /* rpc */
+ /* rpcs */
if (have_rpcs) {
- ly_print(out, "\n rpcs:\n");
+ ly_print(out, "\n%*srpcs:\n", LY_TREE_MOD_DATA_INDENT, "");
+
LY_TREE_FOR(data, node) {
- if (node->nodetype == LYS_RPC) {
- tree_print_rpc_action(out, module, level, indent, node, 0);
- }
+ tree_print_snode(out, 0, 0, node, LYS_RPC, NULL, 0, &opts);
}
}
- /* notification */
+ /* notifications */
if (have_notifs) {
- ly_print(out, "\n notifications:\n");
+ ly_print(out, "\n%*snotifications:\n", LY_TREE_MOD_DATA_INDENT, "");
+
LY_TREE_FOR(data, node) {
- if (node->nodetype == LYS_NOTIF) {
- tree_print_notif(out, module, level, indent, node, 0);
- }
+ tree_print_snode(out, 0, 0, node, LYS_NOTIF, NULL, 0, &opts);
}
}
/* groupings */
- if (have_grps) {
- ly_print(out, "\n groupings:\n");
+ if ((options & LYS_OUTOPT_TREE_GROUPING) && have_grps) {
+ ly_print(out, "\n");
LY_TREE_FOR(data, node) {
if (node->nodetype == LYS_GROUPING) {
- tree_print_grp(out, module, level, indent, node);
+ ly_print(out, "%*sgrouping %s:\n", LY_TREE_MOD_DATA_INDENT, "", node->name);
+
+ tree_print_snode(out, 0, 0, node, LYS_GROUPING, NULL, 0, &opts);
}
}
}
diff --git a/src/printer_yang.c b/src/printer_yang.c
index a93ea3a..b7abe55 100755
--- a/src/printer_yang.c
+++ b/src/printer_yang.c
@@ -459,9 +459,9 @@
char *s;
struct lys_module *mod;
- if (type->module_name) {
+ if (!lys_type_is_local(type)) {
ly_print(out, "%*stype %s:%s", LEVEL, INDENT,
- transform_module_name2import_prefix(module, type->module_name), type->der->name);
+ transform_module_name2import_prefix(module, type->der->module->name), type->der->name);
} else {
ly_print(out, "%*stype %s", LEVEL, INDENT, type->der->name);
}
diff --git a/src/printer_yin.c b/src/printer_yin.c
index 767a277..35c54b1 100644
--- a/src/printer_yin.c
+++ b/src/printer_yin.c
@@ -430,9 +430,9 @@
char *s;
struct lys_module *mod;
- if (type->module_name) {
+ if (!lys_type_is_local(type)) {
ly_print(out, "%*s<type name=\"%s:%s\"", LEVEL, INDENT,
- transform_module_name2import_prefix(module, type->module_name), type->der->name);
+ transform_module_name2import_prefix(module, type->der->module->name), type->der->name);
} else {
yin_print_open(out, level, NULL, "type", "name", type->der->name, content);
}
diff --git a/src/tree_internal.h b/src/tree_internal.h
index 0c16040..700693b 100644
--- a/src/tree_internal.h
+++ b/src/tree_internal.h
@@ -175,6 +175,14 @@
int lys_has_xpath(const struct lys_node *node);
/**
+ * @brief Learn if \p type is defined in the local module or from an import.
+ *
+ * @param[in] type Type to examine.
+ * @return non-zero if local, 0 if from an import.
+ */
+int lys_type_is_local(const struct lys_type *type);
+
+/**
* @brief Create a copy of the specified schema tree \p node
*
* @param[in] module Target module for the duplicated node.
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 15c37e7..e1ff147 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -1581,7 +1581,6 @@
memset(&new, 0, sizeof new);
- new.module_name = lydict_insert(mod->ctx, type->module_name, 0);
new.base = type->base;
new.parent = (struct lys_tpdf *)parent;
@@ -1940,7 +1939,6 @@
{
int i;
- new->module_name = lydict_insert(mod->ctx, old->module_name, 0);
new->base = old->base;
new->der = old->der;
new->parent = (struct lys_tpdf *)parent;
@@ -1980,8 +1978,6 @@
return;
}
- lydict_remove(ctx, type->module_name);
-
lys_extension_instances_free(ctx, type->ext, type->ext_size, private_destructor);
switch (type->base) {
@@ -3248,6 +3244,17 @@
return 0;
}
+int
+lys_type_is_local(const struct lys_type *type)
+{
+ if (!type->der->module) {
+ /* build-in type */
+ return 1;
+ }
+ /* type->parent can be either a typedef or leaf/leaf-list, but module pointers are compatible */
+ return (lys_main_module(type->der->module) == lys_main_module(((struct lys_tpdf *)type->parent)->module));
+}
+
/*
* shallow -
* - do not inherit status from the parent
diff --git a/src/tree_schema.h b/src/tree_schema.h
index c9267cd..8f7f69e 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -189,10 +189,17 @@
LYS_OUT_YANG = 1, /**< YANG schema output format */
LYS_OUT_YIN = 2, /**< YIN schema output format */
LYS_OUT_TREE, /**< Tree schema output format, for more information see the [printers](@ref howtoschemasprinters) page */
- LYS_OUT_TREE_GRPS, /**< Tree schema output format with printing groupings */
LYS_OUT_INFO, /**< Info schema output format, for more information see the [printers](@ref howtoschemasprinters) page */
} LYS_OUTFORMAT;
+/**
+ * @brief Schema output options accepted by libyang [printer functions](@ref howtoschemasprinters).
+ */
+#define LYS_OUTOPT_TREE_RFC 0x01 /**< Conform to the RFC TODO tree output */
+#define LYS_OUTOPT_TREE_GROUPING 0x02 /**< Print groupings separately */
+#define LYS_OUTOPT_TREE_USES 0x04 /**< Print only uses instead the resolved grouping nodes */
+#define LYS_OUTOPT_TREE_NO_LEAFREF 0x08 /**< Do not print the target of leafrefs */
+
/* shortcuts for common in and out formats */
#define LYS_YANG 1 /**< YANG schema format, used for #LYS_INFORMAT and #LYS_OUTFORMAT */
#define LYS_YIN 2 /**< YIN schema format, used for #LYS_INFORMAT and #LYS_OUTFORMAT */
@@ -915,7 +922,6 @@
* @brief YANG type structure providing information from the schema
*/
struct lys_type {
- const char *module_name; /**< module name of the type referenced in der pointer*/
LY_DATA_TYPE base; /**< base type */
uint8_t ext_size; /**< number of elements in #ext array */
struct lys_ext_instance **ext; /**< array of pointers to the extension instances */
@@ -1507,14 +1513,14 @@
const char *ref; /**< reference statement (optional) */
uint16_t flags; /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* values are allowed */
uint8_t ext_size; /**< number of elements in #ext array */
- uint8_t iffeature_size; /**< number of elements in the #iffeature array */
+ uint8_t padding_iffsize; /**< padding byte for the ::lys_node's iffeature_size */
/* non compatible 32b with ::lys_node */
uint16_t unres_count; /**< internal counter for unresolved uses, should be always 0 when the module is parsed */
uint16_t tpdf_size; /**< number of elements in #tpdf array */
struct lys_ext_instance **ext; /**< array of pointers to the extension instances */
- struct lys_iffeature *iffeature; /**< array of if-feature expressions */
+ void *padding_iff; /**< padding pointer for the ::lys_node's iffeature pointer */
struct lys_module *module; /**< pointer to the node's module (mandatory) */
LYS_NODE nodetype; /**< type of the node (mandatory) - #LYS_GROUPING */
@@ -1598,7 +1604,7 @@
uint16_t tpdf_size; /**< number of elements in the #tpdf array */
struct lys_ext_instance **ext; /**< array of pointers to the extension instances */
- void* padding_iff; /**< padding pointer for the ::lys_node's iffeature pointer */
+ void *padding_iff; /**< padding pointer for the ::lys_node's iffeature pointer */
struct lys_module *module; /**< link to the node's data model */
LYS_NODE nodetype; /**< type of the node (mandatory) - #LYS_INPUT or #LYS_OUTPUT */
@@ -2328,63 +2334,66 @@
void *lys_set_private(const struct lys_node *node, void *priv);
/**
- * @brief Print schema tree in the specified format.
- *
- * Same as lys_print(), but it allocates memory and store the data into it.
+ * @brief Print schema tree in the specified format into a memory block.
* It is up to caller to free the returned string by free().
*
* @param[out] strp Pointer to store the resulting dump.
* @param[in] module Schema tree to print.
* @param[in] format Schema output format.
- * @param[in] target_node Optional parameter for ::LYS_OUT_INFO format. It specifies which particular
- * node in the module will be printed.
+ * @param[in] target_node Optional parameter. It specifies which particular node/subtree in the module will be printed.
+ * Use fully qualified schema path (@ref howtoxpath).
+ * @param[in] line_length Maximum characters to be printed on a line. 0 for unlimited.
+ * @param[in] options Schema output options.
* @return 0 on success, 1 on failure (#ly_errno is set).
*/
-int lys_print_mem(char **strp, const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node);
+int lys_print_mem(char **strp, const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node,
+ int line_length, int options);
/**
- * @brief Print schema tree in the specified format.
- *
- * Same as lys_print(), but output is written into the specified file descriptor.
+ * @brief Print schema tree in the specified format into a file descriptor.
*
* @param[in] module Schema tree to print.
* @param[in] fd File descriptor where to print the data.
* @param[in] format Schema output format.
- * @param[in] target_node Optional parameter for ::LYS_OUT_INFO format. It specifies which particular
- * node in the module will be printed.
+ * @param[in] target_node Optional parameter. It specifies which particular node/subtree in the module will be printed.
+ * Use fully qualified schema path (@ref howtoxpath).
+ * @param[in] line_length Maximum characters to be printed on a line. 0 for unlimited.
+ * @param[in] options Schema output options.
* @return 0 on success, 1 on failure (#ly_errno is set).
*/
-int lys_print_fd(int fd, const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node);
+int lys_print_fd(int fd, const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node,
+ int line_length, int options);
/**
- * @brief Print schema tree in the specified format.
- *
- * To write data into a file descriptor, use lys_print_fd().
+ * @brief Print schema tree in the specified format into a file stream.
*
* @param[in] module Schema tree to print.
* @param[in] f File stream where to print the schema.
* @param[in] format Schema output format.
- * @param[in] target_node Optional parameter for ::LYS_OUT_INFO format. It specifies which particular
- * node in the module will be printed.
+ * @param[in] target_node Optional parameter. It specifies which particular node/subtree in the module will be printed.
+ * Use fully qualified schema path (@ref howtoxpath).
+ * @param[in] line_length Maximum characters to be printed on a line. 0 for unlimited.
+ * @param[in] options Schema output options.
* @return 0 on success, 1 on failure (#ly_errno is set).
*/
-int lys_print_file(FILE *f, const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node);
+int lys_print_file(FILE *f, const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node,
+ int line_length, int options);
/**
- * @brief Print schema tree in the specified format.
- *
- * Same as lys_print(), but output is written via provided callback.
+ * @brief Print schema tree in the specified format using a provided callback.
*
* @param[in] module Schema tree to print.
* @param[in] writeclb Callback function to write the data (see write(1)).
* @param[in] arg Optional caller-specific argument to be passed to the \p writeclb callback.
* @param[in] format Schema output format.
- * @param[in] target_node Optional parameter for ::LYS_OUT_INFO format. It specifies which particular
- * node in the module will be printed.
+ * @param[in] target_node Optional parameter. It specifies which particular node/subtree in the module will be printed.
+ * Use fully qualified schema path (@ref howtoxpath).
+ * @param[in] line_length Maximum characters to be printed on a line. 0 for unlimited.
+ * @param[in] options Schema output options.
* @return 0 on success, 1 on failure (#ly_errno is set).
*/
int lys_print_clb(ssize_t (*writeclb)(void *arg, const void *buf, size_t count), void *arg,
- const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node);
+ const struct lys_module *module, LYS_OUTFORMAT format, const char *target_node, int line_length, int options);
/**@} */