blob: 2c83c5558344cde36e07c9946fb39fc580aba52d [file] [log] [blame]
Michal Vasko5ed10f12015-06-04 10:04:57 +02001/**
2 * @file printer/tree.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief TREE printer for libyang data model structure
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 */
21
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
Michal Vaskob5c75d72015-06-15 12:16:52 +020025#include <assert.h>
Michal Vasko5ed10f12015-06-04 10:04:57 +020026
27#include "../common.h"
28#include "../tree.h"
29
Michal Vaskoe03bfbb2015-06-16 09:07:49 +020030/* spec_config = 0 (no special config status), 1 (read-only - rpc output, notification), 2 (write-only - rpc input) */
Michal Vaskofc3b0a32015-06-29 15:50:34 +020031static void tree_print_mnode_choice(FILE *f, struct ly_module* module, int level, char *indent, unsigned int max_name_len,
Michal Vasko64448d72015-07-08 13:35:24 +020032 struct ly_mnode *mnode, int mask, int spec_config, struct ly_submodule *main_submod);
Michal Vaskofc3b0a32015-06-29 15:50:34 +020033static void tree_print_mnode(FILE *f, struct ly_module *module, int level, char *indent, unsigned int max_name_len, struct ly_mnode *mnode,
Michal Vasko64448d72015-07-08 13:35:24 +020034 int mask, int spec_config, struct ly_submodule *main_submod);
Michal Vasko5ed10f12015-06-04 10:04:57 +020035
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020036static int
Michal Vaskoefbb3192015-07-08 10:35:00 +020037is_enabled(struct ly_mnode *mnode)
38{
39 int i;
40
41 for (i = 0; i < mnode->features_size; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +020042 if (!(mnode->features[i]->flags & LYS_FENABLED)) {
Michal Vaskoefbb3192015-07-08 10:35:00 +020043 return 0;
44 }
45 }
46
47 if (mnode->parent && (mnode->parent->nodetype == LY_NODE_AUGMENT)) {
48 for (i = 0; i < mnode->parent->features_size; i++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +020049 if (!(mnode->parent->features[i]->flags & LYS_FENABLED)) {
Michal Vaskoefbb3192015-07-08 10:35:00 +020050 return 0;
51 }
52 }
53 }
54
55 return 1;
56}
57
58static int
Michal Vasko73f94a82015-06-29 16:00:07 +020059sibling_is_valid_child(const struct ly_mnode *mnode, int including)
Michal Vasko6db4fce2015-06-08 14:13:49 +020060{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020061 struct ly_mnode *cur;
Michal Vasko7ea0a312015-06-08 10:36:48 +020062
Michal Vasko07898f92015-06-15 12:17:11 +020063 if (mnode == NULL) {
64 return 0;
65 }
Michal Vasko7ea0a312015-06-08 10:36:48 +020066
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020067 /* has a following printed child */
Michal Vasko73f94a82015-06-29 16:00:07 +020068 LY_TREE_FOR((struct ly_mnode *)(including ? mnode : mnode->next), cur) {
Michal Vasko3d53afd2015-07-08 10:38:09 +020069 if (is_enabled(cur) && (cur->nodetype &
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020070 (LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST | LY_NODE_ANYXML | LY_NODE_CHOICE |
Michal Vasko3d53afd2015-07-08 10:38:09 +020071 LY_NODE_RPC | LY_NODE_INPUT | LY_NODE_OUTPUT | LY_NODE_NOTIF | LY_NODE_CASE))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020072 return 1;
73 }
74 }
Michal Vasko7ea0a312015-06-08 10:36:48 +020075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020076 /* if in uses, the following printed child can actually be in the parent node :-/ */
Michal Vasko07898f92015-06-15 12:17:11 +020077 if (mnode->parent && mnode->parent->nodetype == LY_NODE_USES) {
Michal Vasko73f94a82015-06-29 16:00:07 +020078 return sibling_is_valid_child(mnode->parent, 0);
Michal Vasko07898f92015-06-15 12:17:11 +020079 }
80
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020081 return 0;
Michal Vasko7ea0a312015-06-08 10:36:48 +020082}
83
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020084static char *
Michal Vasko64448d72015-07-08 13:35:24 +020085create_indent(int level, const char *old_indent, const struct ly_mnode *mnode, int shorthand, struct ly_submodule *main_submod)
Michal Vasko449afde2015-06-04 16:06:49 +020086{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020087 int next_is_case = 0, is_case = 0, has_next = 0, i, found;
88 char *new_indent = malloc((level * 4 + 1) * sizeof (char));
Michal Vasko14410462015-06-05 15:08:54 +020089
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020090 strcpy(new_indent, old_indent);
Michal Vasko14410462015-06-05 15:08:54 +020091
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020092 /* this is the indent of a case (standard or shorthand) */
Michal Vasko64448d72015-07-08 13:35:24 +020093 if ((mnode->nodetype == LY_NODE_CASE) || shorthand) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020094 is_case = 1;
95 }
Michal Vasko14410462015-06-05 15:08:54 +020096
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020097 /* this is the direct child of a case */
98 if (!is_case && mnode->parent && (mnode->parent->nodetype & (LY_NODE_CASE | LY_NODE_CHOICE))) {
99 /* it is not the only child */
Michal Vasko64448d72015-07-08 13:35:24 +0200100 if (mnode->next && mnode->next->parent && (mnode->next->parent->nodetype == LY_NODE_CHOICE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200101 next_is_case = 1;
102 }
103 }
Michal Vasko14410462015-06-05 15:08:54 +0200104
Michal Vasko07898f92015-06-15 12:17:11 +0200105 /* next is a node that will actually be printed */
Michal Vasko73f94a82015-06-29 16:00:07 +0200106 has_next = sibling_is_valid_child(mnode, 0);
Michal Vasko14410462015-06-05 15:08:54 +0200107
Michal Vasko07898f92015-06-15 12:17:11 +0200108 /* there is no next, but we are in top-level of a submodule */
Michal Vasko64448d72015-07-08 13:35:24 +0200109 if (!has_next && (mnode->module->type == 1) && !mnode->parent) {
Michal Vasko73f94a82015-06-29 16:00:07 +0200110 struct ly_submodule *submod = (struct ly_submodule *)mnode->module;
111 struct ly_module *mod = submod->belongsto;
Michal Vasko14410462015-06-05 15:08:54 +0200112
Michal Vasko64448d72015-07-08 13:35:24 +0200113 /* a special case when we check the includes of a submodule */
114 if (main_submod) {
115 if (submod != main_submod) {
116 found = 0;
117 for (i = 0; i < main_submod->inc_size; i++) {
118 if (found) {
119 if (mnode->nodetype == LY_NODE_RPC) {
120 has_next = sibling_is_valid_child(main_submod->inc[i].submodule->rpc, 1);
121 } else if (mnode->nodetype == LY_NODE_NOTIF) {
122 has_next = sibling_is_valid_child(main_submod->inc[i].submodule->notif, 1);
123 } else {
124 has_next = sibling_is_valid_child(main_submod->inc[i].submodule->data, 1);
125 }
126 if (has_next) {
127 break;
128 }
129 }
130 if (!found && (submod == main_submod->inc[i].submodule)) {
131 found = 1;
132 }
133 }
134
135 if (!has_next) {
136 if (mnode->nodetype == LY_NODE_RPC) {
137 has_next = sibling_is_valid_child(main_submod->rpc, 1);
138 } else if (mnode->nodetype == LY_NODE_NOTIF) {
139 has_next = sibling_is_valid_child(main_submod->notif, 1);
140 } else {
141 has_next = sibling_is_valid_child(main_submod->data, 1);
142 }
143 }
144 }
145
146 goto strcat_indent;
147 }
148
Michal Vasko07898f92015-06-15 12:17:11 +0200149 /* find this submodule, check all the next ones for valid printed nodes */
150 found = 0;
151 for (i = 0; i < mod->inc_size; i++) {
152 /* we found ours, check all the following submodules and the module */
153 if (found) {
Michal Vaskof2896302015-06-16 09:30:02 +0200154 if (mnode->nodetype == LY_NODE_RPC) {
Michal Vasko73f94a82015-06-29 16:00:07 +0200155 has_next = sibling_is_valid_child(mod->inc[i].submodule->rpc, 1);
Michal Vaskof2896302015-06-16 09:30:02 +0200156 } else if (mnode->nodetype == LY_NODE_NOTIF) {
Michal Vasko73f94a82015-06-29 16:00:07 +0200157 has_next = sibling_is_valid_child(mod->inc[i].submodule->notif, 1);
Michal Vaskof2896302015-06-16 09:30:02 +0200158 } else {
Michal Vasko73f94a82015-06-29 16:00:07 +0200159 has_next = sibling_is_valid_child(mod->inc[i].submodule->data, 1);
Michal Vasko07898f92015-06-15 12:17:11 +0200160 }
Michal Vasko5c7686d2015-07-08 13:36:21 +0200161 if (has_next) {
162 break;
163 }
Michal Vasko07898f92015-06-15 12:17:11 +0200164 }
Michal Vasko5c7686d2015-07-08 13:36:21 +0200165 if (!found && (submod == mod->inc[i].submodule)) {
Michal Vasko07898f92015-06-15 12:17:11 +0200166 found = 1;
167 }
168 }
Michal Vasko7ea0a312015-06-08 10:36:48 +0200169
Michal Vasko07898f92015-06-15 12:17:11 +0200170 /* there is nothing in submodules, check module */
171 if (!has_next) {
Michal Vaskof2896302015-06-16 09:30:02 +0200172 if (mnode->nodetype == LY_NODE_RPC) {
Michal Vasko73f94a82015-06-29 16:00:07 +0200173 has_next = sibling_is_valid_child(mod->rpc, 1);
Michal Vaskof2896302015-06-16 09:30:02 +0200174 } else if (mnode->nodetype == LY_NODE_NOTIF) {
Michal Vasko73f94a82015-06-29 16:00:07 +0200175 has_next = sibling_is_valid_child(mod->notif, 1);
Michal Vaskof2896302015-06-16 09:30:02 +0200176 } else {
Michal Vasko73f94a82015-06-29 16:00:07 +0200177 has_next = sibling_is_valid_child(mod->data, 1);
Michal Vasko07898f92015-06-15 12:17:11 +0200178 }
179 }
180 }
181
Michal Vasko64448d72015-07-08 13:35:24 +0200182strcat_indent:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200183 if (has_next && !next_is_case) {
184 strcat(new_indent, "| ");
185 } else {
186 strcat(new_indent, " ");
187 }
Michal Vasko5ed10f12015-06-04 10:04:57 +0200188
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200189 return new_indent;
Michal Vasko5ed10f12015-06-04 10:04:57 +0200190}
191
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200192static unsigned int
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200193get_max_name_len(struct ly_module *module, struct ly_mnode *mnode)
Michal Vasko8d479bd2015-06-05 10:50:03 +0200194{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200195 struct ly_mnode *sub;
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200196 unsigned int max_name_len = 0, uses_max_name_len, name_len;
Michal Vasko8d479bd2015-06-05 10:50:03 +0200197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200198 LY_TREE_FOR(mnode, sub) {
199 if (sub->nodetype == LY_NODE_USES) {
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200200 uses_max_name_len = get_max_name_len(module, sub->child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200201 if (uses_max_name_len > max_name_len) {
202 max_name_len = uses_max_name_len;
203 }
204 } else if (sub->nodetype &
Michal Vaskoa4d19d42015-07-07 16:10:48 +0200205 (LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST
206 | LY_NODE_ANYXML | LY_NODE_CASE)) {
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200207 name_len = strlen(sub->name) + (module == sub->module ? 0 : strlen(sub->module->prefix)+1);
208 if (name_len > max_name_len) {
209 max_name_len = name_len;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200210 }
211 }
212 }
Michal Vasko8d479bd2015-06-05 10:50:03 +0200213
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200214 return max_name_len;
Michal Vasko8d479bd2015-06-05 10:50:03 +0200215}
216
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200217static void
Radek Krejci1574a8d2015-08-03 14:16:52 +0200218tree_print_type(FILE *f, struct lys_type *type)
Michal Vasko5ed10f12015-06-04 10:04:57 +0200219{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200220 if (type->base == LY_TYPE_LEAFREF) {
221 fprintf(f, "-> %s", type->info.lref.path);
222 } else if (type->prefix) {
223 fprintf(f, "%s:%s", type->prefix, type->der->name);
224 } else {
225 fprintf(f, "%s", type->der->name);
226 }
Michal Vasko5ed10f12015-06-04 10:04:57 +0200227}
228
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200229static void
Michal Vasko28c6b572015-06-18 12:43:31 +0200230tree_print_features(FILE *f, const struct ly_feature **features, uint8_t features_size)
231{
232 int i;
233
234 if (!features_size) {
235 return;
236 }
237
238 fprintf(f, " {");
239 for (i = 0; i < features_size; i++) {
240 if (i > 0) {
241 fprintf(f, ",");
242 }
243 fprintf(f, "%s", features[i]->name);
244 }
245 fprintf(f, "}?");
246}
247
248static void
Michal Vasko64448d72015-07-08 13:35:24 +0200249tree_print_input_output(FILE *f, struct ly_module *module, int level, char *indent, struct ly_mnode *mnode, int spec_config, struct ly_submodule *main_submod)
Michal Vaskob5c75d72015-06-15 12:16:52 +0200250{
251 unsigned int max_child_len;
252 char *new_indent;
253 struct ly_mnode *sub;
254
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200255 assert(spec_config);
Michal Vaskob5c75d72015-06-15 12:16:52 +0200256
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200257 fprintf(f, "%s+--%s %s\n", indent, (spec_config == 1 ? "-w" : "ro"), (spec_config == 1 ? "input" : "output"));
Michal Vaskob5c75d72015-06-15 12:16:52 +0200258
259 level++;
Michal Vasko64448d72015-07-08 13:35:24 +0200260 new_indent = create_indent(level, indent, mnode, 0, main_submod);
Michal Vaskob5c75d72015-06-15 12:16:52 +0200261
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200262 max_child_len = get_max_name_len(module, mnode->child);
Michal Vaskob5c75d72015-06-15 12:16:52 +0200263
264 LY_TREE_FOR(mnode->child, sub) {
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200265 tree_print_mnode(f, module, level, new_indent, max_child_len, sub,
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200266 LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST | LY_NODE_ANYXML | LY_NODE_USES,
Michal Vasko64448d72015-07-08 13:35:24 +0200267 spec_config, main_submod);
Michal Vaskob5c75d72015-06-15 12:16:52 +0200268 }
269
270 free(new_indent);
271}
272
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200273static void
Michal Vasko64448d72015-07-08 13:35:24 +0200274tree_print_container(FILE *f, struct ly_module *module, int level, char *indent, struct ly_mnode *mnode, int spec_config, struct ly_submodule *main_submod)
Michal Vasko5ed10f12015-06-04 10:04:57 +0200275{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200276 unsigned int max_child_len;
277 char *new_indent;
278 struct ly_mnode_container *cont = (struct ly_mnode_container *)mnode;
279 struct ly_mnode *sub;
Michal Vasko5ed10f12015-06-04 10:04:57 +0200280
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200281 assert(spec_config >= 0 && spec_config <= 2);
Michal Vaskob5c75d72015-06-15 12:16:52 +0200282
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200283 fprintf(f, "%s%s--", indent,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200284 (cont->flags & LYS_STATUS_DEPRC ? "x" : (cont->flags & LYS_STATUS_OBSLT ? "o" : "+")));
Michal Vaskob5c75d72015-06-15 12:16:52 +0200285
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200286 if (spec_config == 0) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200287 fprintf(f, "%s ", (cont->flags & LYS_CONFIG_W ? "rw" : "ro"));
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200288 } else if (spec_config == 1) {
Michal Vaskob5c75d72015-06-15 12:16:52 +0200289 fprintf(f, "-w ");
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200290 } else if (spec_config == 2) {
Michal Vaskob5c75d72015-06-15 12:16:52 +0200291 fprintf(f, "ro ");
292 }
293
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200294 if (module != cont->module) {
295 fprintf(f, "%s:", cont->module->prefix);
296 }
297
Michal Vasko28c6b572015-06-18 12:43:31 +0200298 fprintf(f, "%s%s", cont->name, (cont->presence ? "!" : ""));
299
300 tree_print_features(f, (const struct ly_feature **)cont->features, cont->features_size);
301
302 fprintf(f, "\n");
Michal Vasko5ed10f12015-06-04 10:04:57 +0200303
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200304 level++;
Michal Vasko64448d72015-07-08 13:35:24 +0200305 new_indent = create_indent(level, indent, mnode, 0, main_submod);
Michal Vasko5ed10f12015-06-04 10:04:57 +0200306
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200307 max_child_len = get_max_name_len(module, mnode->child);
Michal Vasko449afde2015-06-04 16:06:49 +0200308
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200309 LY_TREE_FOR(cont->child, sub) {
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200310 tree_print_mnode(f, module, level, new_indent, max_child_len, sub,
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200311 LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST | LY_NODE_ANYXML | LY_NODE_USES,
Michal Vasko64448d72015-07-08 13:35:24 +0200312 spec_config, main_submod);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200313 }
Michal Vasko5ed10f12015-06-04 10:04:57 +0200314
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200315 free(new_indent);
Michal Vasko5ed10f12015-06-04 10:04:57 +0200316}
317
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200318static void
Michal Vasko64448d72015-07-08 13:35:24 +0200319tree_print_choice(FILE *f, struct ly_module *module, int level, char *indent, struct ly_mnode *mnode, int spec_config, struct ly_submodule *main_submod)
Michal Vasko5ed10f12015-06-04 10:04:57 +0200320{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200321 unsigned int max_child_len;
322 char *new_indent;
323 struct ly_mnode_choice *choice = (struct ly_mnode_choice *)mnode;
324 struct ly_mnode *sub;
Michal Vasko5ed10f12015-06-04 10:04:57 +0200325
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200326 assert(spec_config >= 0 && spec_config <= 2);
Michal Vaskob5c75d72015-06-15 12:16:52 +0200327
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200328 fprintf(f, "%s%s--", indent,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200329 (choice->flags & LYS_STATUS_DEPRC ? "x" : (choice->flags & LYS_STATUS_OBSLT ? "o" : "+")));
Michal Vaskob5c75d72015-06-15 12:16:52 +0200330
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200331 if (spec_config == 0) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200332 fprintf(f, "%s ", (choice->flags & LYS_CONFIG_W ? "rw" : "ro"));
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200333 } else if (spec_config == 1) {
Michal Vaskob5c75d72015-06-15 12:16:52 +0200334 fprintf(f, "-w ");
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200335 } else if (spec_config == 2) {
Michal Vaskob5c75d72015-06-15 12:16:52 +0200336 fprintf(f, "ro ");
337 }
338
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200339 fprintf(f, "(");
340
341 if (module != choice->module) {
342 fprintf(f, "%s:", choice->module->prefix);
343 }
344
Radek Krejci1574a8d2015-08-03 14:16:52 +0200345 fprintf(f, "%s)%s", choice->name, (choice->flags & LYS_MAND_TRUE ? "" : "?"));
Michal Vaskob5c75d72015-06-15 12:16:52 +0200346
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200347 if (choice->dflt != NULL) {
348 fprintf(f, " <%s>", choice->dflt->name);
349 }
Michal Vasko28c6b572015-06-18 12:43:31 +0200350
351 tree_print_features(f, (const struct ly_feature **)choice->features, choice->features_size);
352
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200353 fprintf(f, "\n");
Michal Vasko449afde2015-06-04 16:06:49 +0200354
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200355 level++;
Michal Vasko64448d72015-07-08 13:35:24 +0200356 new_indent = create_indent(level, indent, mnode, 0, main_submod);
Michal Vasko449afde2015-06-04 16:06:49 +0200357
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200358 max_child_len = get_max_name_len(module, mnode->child);
Michal Vasko449afde2015-06-04 16:06:49 +0200359
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200360 LY_TREE_FOR(choice->child, sub) {
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200361 tree_print_mnode_choice(f, module, level, new_indent, max_child_len, sub,
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200362 LY_NODE_CASE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST | LY_NODE_ANYXML,
Michal Vasko64448d72015-07-08 13:35:24 +0200363 spec_config, main_submod);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200364 }
Michal Vasko449afde2015-06-04 16:06:49 +0200365
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200366 free(new_indent);
Michal Vasko449afde2015-06-04 16:06:49 +0200367}
368
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200369static void
Michal Vasko64448d72015-07-08 13:35:24 +0200370tree_print_case(FILE *f, struct ly_module *module, int level, char *indent, unsigned int max_name_len, struct ly_mnode *mnode, int shorthand, int spec_config, struct ly_submodule *main_submod)
Michal Vasko449afde2015-06-04 16:06:49 +0200371{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200372 char *new_indent;
373 struct ly_mnode_case *cas = (struct ly_mnode_case *)mnode;
374 struct ly_mnode *sub;
Radek Krejci7e97c352015-06-19 16:26:34 +0200375
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200376 fprintf(f, "%s%s--:(", indent,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200377 (cas->flags & LYS_STATUS_DEPRC ? "x" : (cas->flags & LYS_STATUS_OBSLT ? "o" : "+")));
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200378
379 if (module != cas->module) {
380 fprintf(f, "%s:", cas->module->prefix);
381 }
382
383 fprintf(f, "%s)", cas->name);
Michal Vasko449afde2015-06-04 16:06:49 +0200384
Michal Vasko28c6b572015-06-18 12:43:31 +0200385 tree_print_features(f, (const struct ly_feature **)cas->features, cas->features_size);
386
387 fprintf(f, "\n");
388
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200389 level++;
Michal Vasko64448d72015-07-08 13:35:24 +0200390 new_indent = create_indent(level, indent, mnode, shorthand, main_submod);
Michal Vasko449afde2015-06-04 16:06:49 +0200391
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200392 if (shorthand) {
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200393 tree_print_mnode(f, module, level, new_indent, max_name_len, mnode,
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200394 LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST | LY_NODE_ANYXML | LY_NODE_USES,
Michal Vasko64448d72015-07-08 13:35:24 +0200395 spec_config, main_submod);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200396 } else {
397 LY_TREE_FOR(mnode->child, sub) {
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200398 tree_print_mnode(f, module, level, new_indent, max_name_len, sub,
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200399 LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST | LY_NODE_ANYXML | LY_NODE_USES,
Michal Vasko64448d72015-07-08 13:35:24 +0200400 spec_config, main_submod);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200401 }
402 }
Michal Vasko449afde2015-06-04 16:06:49 +0200403
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200404 free(new_indent);
Michal Vasko5ed10f12015-06-04 10:04:57 +0200405}
406
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200407static void
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200408tree_print_anyxml(FILE *f, struct ly_module *module, char *indent, unsigned int max_name_len, struct ly_mnode *mnode, int spec_config)
Michal Vasko315f70b2015-06-05 10:48:59 +0200409{
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200410 uint8_t prefix_len;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200411 struct ly_mnode_anyxml *anyxml = (struct ly_mnode_anyxml *)mnode;
Michal Vasko315f70b2015-06-05 10:48:59 +0200412
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200413 assert(spec_config >= 0 && spec_config <= 2);
Michal Vaskob5c75d72015-06-15 12:16:52 +0200414
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200415 fprintf(f, "%s%s--", indent,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200416 (anyxml->flags & LYS_STATUS_DEPRC ? "x" : (anyxml->flags & LYS_STATUS_OBSLT ? "o" : "+")));
Michal Vaskob5c75d72015-06-15 12:16:52 +0200417
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200418 if (spec_config == 0) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200419 fprintf(f, "%s ", (anyxml->flags & LYS_CONFIG_W ? "rw" : "ro"));
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200420 } else if (spec_config == 1) {
Michal Vaskob5c75d72015-06-15 12:16:52 +0200421 fprintf(f, "-w ");
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200422 } else if (spec_config == 2) {
Michal Vaskob5c75d72015-06-15 12:16:52 +0200423 fprintf(f, "ro ");
424 }
425
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200426 prefix_len = 0;
427 if (module != anyxml->module) {
428 fprintf(f, "%s:", anyxml->module->prefix);
429 prefix_len = strlen(anyxml->module->prefix)+1;
430 }
431
Radek Krejci1574a8d2015-08-03 14:16:52 +0200432 fprintf(f, "%s%s%*sanyxml", anyxml->name, (anyxml->flags & LYS_MAND_TRUE ? " " : "?"),
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200433 3 + (int)((max_name_len - strlen(anyxml->name)) - prefix_len), " ");
Michal Vasko28c6b572015-06-18 12:43:31 +0200434
435 tree_print_features(f, (const struct ly_feature **)anyxml->features, anyxml->features_size);
436
437 fprintf(f, "\n");
Michal Vasko315f70b2015-06-05 10:48:59 +0200438}
439
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200440static void
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200441tree_print_leaf(FILE *f, struct ly_module *module, char *indent, unsigned int max_name_len, struct ly_mnode *mnode, int spec_config)
Michal Vasko5ed10f12015-06-04 10:04:57 +0200442{
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200443 uint8_t prefix_len;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200444 struct ly_mnode_leaf *leaf = (struct ly_mnode_leaf *)mnode;
Michal Vasko96929d92015-08-03 15:30:22 +0200445 struct ly_mnode *parent;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200446 struct ly_mnode_list *list;
447 int i, is_key = 0;
Michal Vasko449afde2015-06-04 16:06:49 +0200448
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200449 assert(spec_config >= 0 && spec_config <= 2);
Michal Vaskob5c75d72015-06-15 12:16:52 +0200450
Michal Vasko96929d92015-08-03 15:30:22 +0200451 for (parent = leaf->parent; parent && parent->nodetype == LY_NODE_USES; parent = parent->parent);
452 if (parent->nodetype == LY_NODE_LIST) {
453 list = (struct ly_mnode_list *)parent;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200454 for (i = 0; i < list->keys_size; i++) {
Michal Vasko96929d92015-08-03 15:30:22 +0200455 if (list->keys[i] == leaf) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200456 is_key = 1;
457 break;
458 }
459 }
460 }
Michal Vasko449afde2015-06-04 16:06:49 +0200461
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200462 fprintf(f, "%s%s--", indent,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200463 (leaf->flags & LYS_STATUS_DEPRC ? "x" : (leaf->flags & LYS_STATUS_OBSLT ? "o" : "+")));
Michal Vaskob5c75d72015-06-15 12:16:52 +0200464
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200465 if (spec_config == 0) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200466 fprintf(f, "%s ", (leaf->flags & LYS_CONFIG_W ? "rw" : "ro"));
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200467 } else if (spec_config == 1) {
Michal Vaskob5c75d72015-06-15 12:16:52 +0200468 fprintf(f, "-w ");
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200469 } else if (spec_config == 2) {
Michal Vaskob5c75d72015-06-15 12:16:52 +0200470 fprintf(f, "ro ");
471 }
472
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200473 prefix_len = 0;
474 if (module != leaf->module) {
475 fprintf(f, "%s:", leaf->module->prefix);
476 prefix_len = strlen(leaf->module->prefix)+1;
477 }
478
Radek Krejci1574a8d2015-08-03 14:16:52 +0200479 fprintf(f, "%s%s%*s", leaf->name, ((leaf->flags & LYS_MAND_TRUE) || is_key ? " " : "?"),
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200480 3 + (int)((max_name_len - strlen(leaf->name)) - prefix_len), " ");
Michal Vaskob5c75d72015-06-15 12:16:52 +0200481
482 tree_print_type(f, &leaf->type);
483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200484 if (leaf->dflt != NULL) {
485 fprintf(f, " <%s>", leaf->dflt);
486 }
Michal Vasko28c6b572015-06-18 12:43:31 +0200487
488 tree_print_features(f, (const struct ly_feature **)leaf->features, leaf->features_size);
489
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200490 fprintf(f, "\n");
Michal Vasko5ed10f12015-06-04 10:04:57 +0200491}
492
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200493static void
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200494tree_print_leaflist(FILE *f, struct ly_module *module, char *indent, unsigned int max_name_len, struct ly_mnode *mnode, int spec_config)
Michal Vasko5ed10f12015-06-04 10:04:57 +0200495{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200496 struct ly_mnode_leaflist *leaflist = (struct ly_mnode_leaflist *)mnode;
Michal Vasko449afde2015-06-04 16:06:49 +0200497
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200498 assert(spec_config >= 0 && spec_config <= 2);
Michal Vaskob5c75d72015-06-15 12:16:52 +0200499
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200500 fprintf(f, "%s%s--", indent,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200501 (leaflist->flags & LYS_STATUS_DEPRC ? "x" : (leaflist->flags & LYS_STATUS_OBSLT ? "o" : "+")));
Michal Vaskob5c75d72015-06-15 12:16:52 +0200502
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200503 if (spec_config == 0) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200504 fprintf(f, "%s ", (leaflist->flags & LYS_CONFIG_W ? "rw" : "ro"));
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200505 } else if (spec_config == 1) {
Michal Vaskob5c75d72015-06-15 12:16:52 +0200506 fprintf(f, "-w ");
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200507 } else if (spec_config == 2) {
Michal Vaskob5c75d72015-06-15 12:16:52 +0200508 fprintf(f, "ro ");
509 }
510
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200511 if (module != leaflist->module) {
512 fprintf(f, "%s:", leaflist->module->prefix);
513 }
514
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200515 fprintf(f, "%s*%*s", leaflist->name, 3 + (int)(max_name_len - strlen(leaflist->name)), " ");
Michal Vaskob5c75d72015-06-15 12:16:52 +0200516
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200517 tree_print_type(f, &leaflist->type);
Michal Vaskob5c75d72015-06-15 12:16:52 +0200518
Michal Vasko28c6b572015-06-18 12:43:31 +0200519 tree_print_features(f, (const struct ly_feature **)leaflist->features, leaflist->features_size);
520
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200521 fprintf(f, "\n");
Michal Vasko5ed10f12015-06-04 10:04:57 +0200522}
523
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200524static void
Michal Vasko64448d72015-07-08 13:35:24 +0200525tree_print_list(FILE *f, struct ly_module *module, int level, char *indent, struct ly_mnode *mnode, int spec_config, struct ly_submodule *main_submod)
Michal Vasko5ed10f12015-06-04 10:04:57 +0200526{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200527 int i;
528 unsigned int max_child_len;
529 char *new_indent;
530 struct ly_mnode *sub;
531 struct ly_mnode_list *list = (struct ly_mnode_list *)mnode;
Michal Vasko5ed10f12015-06-04 10:04:57 +0200532
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200533 fprintf(f, "%s%s--", indent,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200534 (list->flags & LYS_STATUS_DEPRC ? "x" : (list->flags & LYS_STATUS_OBSLT ? "o" : "+")));
Michal Vaskob5c75d72015-06-15 12:16:52 +0200535
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200536 if (spec_config == 0) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200537 fprintf(f, "%s ", (list->flags & LYS_CONFIG_W ? "rw" : "ro"));
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200538 } else if (spec_config == 1) {
Michal Vaskob5c75d72015-06-15 12:16:52 +0200539 fprintf(f, "-w ");
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200540 } else if (spec_config == 2) {
Michal Vaskob5c75d72015-06-15 12:16:52 +0200541 fprintf(f, "ro ");
542 }
543
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200544 if (module != list->module) {
545 fprintf(f, "%s:", list->module->prefix);
546 }
547
Michal Vaskob5c75d72015-06-15 12:16:52 +0200548 fprintf(f, "%s*", list->name);
Michal Vasko5ed10f12015-06-04 10:04:57 +0200549
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200550 for (i = 0; i < list->keys_size; i++) {
551 if (i == 0) {
552 fprintf(f, " [");
553 }
554 fprintf(f, "%s%s", list->keys[i]->name, i + 1 < list->keys_size ? "," : "]");
555 }
Michal Vaskob5c75d72015-06-15 12:16:52 +0200556
Michal Vasko28c6b572015-06-18 12:43:31 +0200557 tree_print_features(f, (const struct ly_feature **)list->features, list->features_size);
558
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200559 fprintf(f, "\n");
Michal Vasko5ed10f12015-06-04 10:04:57 +0200560
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200561 level++;
Michal Vasko64448d72015-07-08 13:35:24 +0200562 new_indent = create_indent(level, indent, mnode, 0, main_submod);
Michal Vasko5ed10f12015-06-04 10:04:57 +0200563
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200564 max_child_len = get_max_name_len(module, mnode->child);
Michal Vasko449afde2015-06-04 16:06:49 +0200565
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200566 LY_TREE_FOR(mnode->child, sub) {
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200567 tree_print_mnode(f, module, level, new_indent, max_child_len, sub,
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200568 LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST | LY_NODE_USES | LY_NODE_ANYXML,
Michal Vasko64448d72015-07-08 13:35:24 +0200569 spec_config, main_submod);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200570 }
Michal Vasko5ed10f12015-06-04 10:04:57 +0200571
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200572 free(new_indent);
Michal Vasko5ed10f12015-06-04 10:04:57 +0200573}
574
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200575static void
Michal Vasko64448d72015-07-08 13:35:24 +0200576tree_print_uses(FILE *f, struct ly_module *module, int level, char *indent, unsigned int max_name_len, struct ly_mnode *mnode, int spec_config, struct ly_submodule *main_submod)
Michal Vasko5ed10f12015-06-04 10:04:57 +0200577{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200578 struct ly_mnode *node;
579 struct ly_mnode_uses *uses = (struct ly_mnode_uses *)mnode;
Radek Krejci7e97c352015-06-19 16:26:34 +0200580
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200581 LY_TREE_FOR(uses->child, node) {
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200582 tree_print_mnode(f, module, level, indent, max_name_len, node,
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200583 LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST | LY_NODE_USES | LY_NODE_ANYXML,
Michal Vasko64448d72015-07-08 13:35:24 +0200584 spec_config, main_submod);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200585 }
Michal Vasko5ed10f12015-06-04 10:04:57 +0200586}
587
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200588static void
Michal Vasko64448d72015-07-08 13:35:24 +0200589tree_print_rpc(FILE *f, struct ly_module *module, int level, char *indent, struct ly_mnode *mnode, struct ly_submodule *main_submod)
Michal Vaskob5c75d72015-06-15 12:16:52 +0200590{
591 char *new_indent;
592 struct ly_mnode *node;
593 struct ly_mnode_rpc *rpc = (struct ly_mnode_rpc *)mnode;
Radek Krejci7e97c352015-06-19 16:26:34 +0200594
Michal Vaskoefbb3192015-07-08 10:35:00 +0200595 if (!is_enabled(mnode)) {
596 return;
Radek Krejci7e97c352015-06-19 16:26:34 +0200597 }
Michal Vaskob5c75d72015-06-15 12:16:52 +0200598
Michal Vasko28c6b572015-06-18 12:43:31 +0200599 fprintf(f, "%s%s---x %s", indent,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200600 (rpc->flags & LYS_STATUS_DEPRC ? "x" : (rpc->flags & LYS_STATUS_OBSLT ? "o" : "+")), rpc->name);
Michal Vaskob5c75d72015-06-15 12:16:52 +0200601
Michal Vasko28c6b572015-06-18 12:43:31 +0200602 tree_print_features(f, (const struct ly_feature **)rpc->features, rpc->features_size);
603
604 fprintf(f, "\n");
605
Michal Vaskob5c75d72015-06-15 12:16:52 +0200606 level++;
Michal Vasko64448d72015-07-08 13:35:24 +0200607 new_indent = create_indent(level, indent, mnode, 0, main_submod);
Michal Vaskob5c75d72015-06-15 12:16:52 +0200608
609 LY_TREE_FOR(rpc->child, node) {
610 if (node->nodetype == LY_NODE_INPUT) {
Michal Vasko64448d72015-07-08 13:35:24 +0200611 tree_print_input_output(f, module, level, new_indent, node, 1, main_submod);
Michal Vaskob5c75d72015-06-15 12:16:52 +0200612 } else if (node->nodetype == LY_NODE_OUTPUT) {
Michal Vasko64448d72015-07-08 13:35:24 +0200613 tree_print_input_output(f, module, level, new_indent, node, 2, main_submod);
Michal Vaskob5c75d72015-06-15 12:16:52 +0200614 }
615 }
616
617 free(new_indent);
618}
619
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200620static void
Michal Vasko64448d72015-07-08 13:35:24 +0200621tree_print_notif(FILE *f, struct ly_module *module, int level, char *indent, struct ly_mnode *mnode, struct ly_submodule *main_submod)
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200622{
623 unsigned int max_child_len;
624 char *new_indent;
625 struct ly_mnode *node;
626 struct ly_mnode_notif *notif = (struct ly_mnode_notif *)mnode;
Radek Krejci7e97c352015-06-19 16:26:34 +0200627
Michal Vaskoefbb3192015-07-08 10:35:00 +0200628 if (!is_enabled(mnode)) {
629 return;
Radek Krejci7e97c352015-06-19 16:26:34 +0200630 }
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200631
Michal Vasko28c6b572015-06-18 12:43:31 +0200632 fprintf(f, "%s%s---n %s", indent,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200633 (notif->flags & LYS_STATUS_DEPRC ? "x" : (notif->flags & LYS_STATUS_OBSLT ? "o" : "+")),
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200634 notif->name);
635
Michal Vasko28c6b572015-06-18 12:43:31 +0200636 tree_print_features(f, (const struct ly_feature **)notif->features, notif->features_size);
637
638 fprintf(f, "\n");
639
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200640 level++;
Michal Vasko64448d72015-07-08 13:35:24 +0200641 new_indent = create_indent(level, indent, mnode, 0, main_submod);
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200642
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200643 max_child_len = get_max_name_len(module, mnode->child);
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200644
645 LY_TREE_FOR(notif->child, node) {
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200646 tree_print_mnode(f, module, level, new_indent, max_child_len, node,
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200647 LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST | LY_NODE_ANYXML | LY_NODE_USES,
Michal Vasko64448d72015-07-08 13:35:24 +0200648 2, main_submod);
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200649 }
650
651 free(new_indent);
652}
653
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200654static void
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200655tree_print_mnode_choice(FILE *f, struct ly_module *module, int level, char *indent, unsigned int max_name_len, struct ly_mnode *mnode, int mask,
Michal Vasko64448d72015-07-08 13:35:24 +0200656 int spec_config, struct ly_submodule *main_submod)
Michal Vasko5ed10f12015-06-04 10:04:57 +0200657{
Michal Vaskoefbb3192015-07-08 10:35:00 +0200658 if (!is_enabled(mnode)) {
659 return;
660 }
661
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200662 if (mnode->nodetype & mask) {
663 if (mnode->nodetype == LY_NODE_CASE) {
Michal Vasko64448d72015-07-08 13:35:24 +0200664 tree_print_case(f, module, level, indent, max_name_len, mnode, 0, spec_config, main_submod);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200665 } else {
Michal Vasko64448d72015-07-08 13:35:24 +0200666 tree_print_case(f, module, level, indent, max_name_len, mnode, 1, spec_config, main_submod);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200667 }
668 }
Michal Vasko5ed10f12015-06-04 10:04:57 +0200669}
670
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200671static void
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200672tree_print_mnode(FILE *f, struct ly_module *module, int level, char *indent, unsigned int max_name_len, struct ly_mnode *mnode, int mask,
Michal Vasko64448d72015-07-08 13:35:24 +0200673 int spec_config, struct ly_submodule *main_submod)
Michal Vasko5ed10f12015-06-04 10:04:57 +0200674{
Michal Vaskoefbb3192015-07-08 10:35:00 +0200675 if (!is_enabled(mnode)) {
676 return;
Radek Krejci87e840c2015-06-19 16:44:54 +0200677 }
678
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200679 switch (mnode->nodetype & mask) {
680 case LY_NODE_CONTAINER:
Michal Vasko64448d72015-07-08 13:35:24 +0200681 tree_print_container(f, module, level, indent, mnode, spec_config, main_submod);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200682 break;
683 case LY_NODE_CHOICE:
Michal Vasko64448d72015-07-08 13:35:24 +0200684 tree_print_choice(f, module, level, indent, mnode, spec_config, main_submod);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200685 break;
686 case LY_NODE_LEAF:
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200687 tree_print_leaf(f, module, indent, max_name_len, mnode, spec_config);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200688 break;
689 case LY_NODE_LEAFLIST:
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200690 tree_print_leaflist(f, module, indent, max_name_len, mnode, spec_config);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200691 break;
692 case LY_NODE_LIST:
Michal Vasko64448d72015-07-08 13:35:24 +0200693 tree_print_list(f, module, level, indent, mnode, spec_config, main_submod);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200694 break;
695 case LY_NODE_ANYXML:
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200696 tree_print_anyxml(f, module, indent, max_name_len, mnode, spec_config);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200697 break;
698 case LY_NODE_USES:
Michal Vasko64448d72015-07-08 13:35:24 +0200699 tree_print_uses(f, module, level, indent, max_name_len, mnode, spec_config, main_submod);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200700 break;
701 default:
702 break;
703 }
Michal Vasko5ed10f12015-06-04 10:04:57 +0200704}
705
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200706int
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200707tree_print_model(FILE *f, struct ly_module *module)
Michal Vasko5ed10f12015-06-04 10:04:57 +0200708{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200709 struct ly_mnode *mnode;
Michal Vasko64448d72015-07-08 13:35:24 +0200710 struct ly_submodule *submod;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200711 unsigned int max_child_len;
712 int level = 1, i, have_rpcs = 0, have_notifs = 0;
713 char *indent = malloc((level * 4 + 1) * sizeof (char));
714 strcpy(indent, " ");
Michal Vasko5ed10f12015-06-04 10:04:57 +0200715
Michal Vaskofc6ac172015-07-07 09:46:46 +0200716 if (module->type) {
Michal Vasko64448d72015-07-08 13:35:24 +0200717 submod = (struct ly_submodule *)module;
718 fprintf(f, "submodule: %s (belongs-to %s)\n", submod->name, submod->belongsto->name);
Michal Vaskofc6ac172015-07-07 09:46:46 +0200719 } else {
Michal Vasko64448d72015-07-08 13:35:24 +0200720 submod = NULL;
Michal Vaskofc6ac172015-07-07 09:46:46 +0200721 fprintf(f, "module: %s\n", module->name);
722 }
Michal Vasko5ed10f12015-06-04 10:04:57 +0200723
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200724 /* included submodules */
725 for (i = 0; i < module->inc_size; i++) {
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200726 max_child_len = get_max_name_len((struct ly_module *)module->inc[i].submodule, module->inc[i].submodule->data);
Michal Vasko8d479bd2015-06-05 10:50:03 +0200727
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200728 LY_TREE_FOR(module->inc[i].submodule->data, mnode) {
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200729 tree_print_mnode(f, (struct ly_module *)module->inc[i].submodule, level, indent, max_child_len, mnode,
Michal Vasko6a17ca32015-07-08 10:36:01 +0200730 LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST
Michal Vasko64448d72015-07-08 13:35:24 +0200731 | LY_NODE_ANYXML | LY_NODE_USES, 0, submod);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200732 }
733 }
Michal Vasko5ed10f12015-06-04 10:04:57 +0200734
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200735 /* module */
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200736 max_child_len = get_max_name_len(module, module->data);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200737 level++;
Michal Vasko5ed10f12015-06-04 10:04:57 +0200738
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200739 LY_TREE_FOR(module->data, mnode) {
Michal Vaskofc3b0a32015-06-29 15:50:34 +0200740 tree_print_mnode(f, module, level, indent, max_child_len, mnode,
Michal Vasko6a17ca32015-07-08 10:36:01 +0200741 LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST
Michal Vasko64448d72015-07-08 13:35:24 +0200742 | LY_NODE_ANYXML | LY_NODE_USES, 0, submod);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200743 }
Michal Vasko5ed10f12015-06-04 10:04:57 +0200744
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200745 /* rpc */
746 if (module->rpc) {
Michal Vaskob5c75d72015-06-15 12:16:52 +0200747 have_rpcs = 1;
748 } else {
749 for (i = 0; i < module->inc_size; i++) {
750 if (module->inc[i].submodule->rpc) {
751 have_rpcs = 1;
752 break;
753 }
754 }
755 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200756 if (have_rpcs) {
Michal Vaskob5c75d72015-06-15 12:16:52 +0200757 fprintf(f, "rpcs:\n");
758 for (i = 0; i < module->inc_size; i++) {
759 LY_TREE_FOR(module->inc[i].submodule->rpc, mnode) {
Michal Vasko64448d72015-07-08 13:35:24 +0200760 tree_print_rpc(f, (struct ly_module *)module->inc[i].submodule, level, indent, mnode, submod);
Michal Vaskob5c75d72015-06-15 12:16:52 +0200761 }
762 }
763 LY_TREE_FOR(module->rpc, mnode) {
Michal Vasko64448d72015-07-08 13:35:24 +0200764 tree_print_rpc(f, module, level, indent, mnode, submod);
Michal Vaskob5c75d72015-06-15 12:16:52 +0200765 }
766 }
Michal Vasko449afde2015-06-04 16:06:49 +0200767
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200768 /* notification */
769 if (module->notif) {
770 have_notifs = 1;
771 } else {
772 for (i = 0; i < module->inc_size; i++) {
773 if (module->inc[i].submodule->notif) {
774 have_notifs = 1;
775 break;
776 }
777 }
778 }
779 if (have_notifs) {
780 fprintf(f, "notifications:\n");
781 for (i = 0; i < module->inc_size; i++) {
782 LY_TREE_FOR(module->inc[i].submodule->notif, mnode) {
Michal Vasko64448d72015-07-08 13:35:24 +0200783 tree_print_notif(f, (struct ly_module *)module->inc[i].submodule, level, indent, mnode, submod);
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200784 }
785 }
786 LY_TREE_FOR(module->notif, mnode) {
Michal Vasko64448d72015-07-08 13:35:24 +0200787 tree_print_notif(f, module, level, indent, mnode, submod);
Michal Vaskoe03bfbb2015-06-16 09:07:49 +0200788 }
789 }
Michal Vasko449afde2015-06-04 16:06:49 +0200790
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200791 free(indent);
792 return EXIT_SUCCESS;
Michal Vasko5ed10f12015-06-04 10:04:57 +0200793}