blob: 27b20082ee6d7638164870da363f992b5dfbf9d3 [file] [log] [blame]
Michal Vaskoa63ca342016-02-05 14:29:19 +01001/**
2 * @file printer_yin.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief YIN printer for libyang data model structure
5 *
6 * Copyright (c) 2016 CESNET, z.s.p.o.
7 *
Radek Krejci54f6fb32016-02-24 12:56:39 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
Michal Vasko8de098c2016-02-26 10:00:25 +010011 *
Radek Krejci54f6fb32016-02-24 12:56:39 +010012 * https://opensource.org/licenses/BSD-3-Clause
Michal Vaskoa63ca342016-02-05 14:29:19 +010013 */
14
15#include <stdlib.h>
16#include <string.h>
17
18#include "common.h"
19#include "printer.h"
20#include "tree_schema.h"
21#include "xml_internal.h"
22
23#define INDENT ""
24#define LEVEL (level*2)
25
26static void yin_print_snode(struct lyout *out, int level, const struct lys_node *node, int mask);
27
28static void
Michal Vasko87bb46b2016-02-12 11:51:42 +010029yin_print_open(struct lyout *out, int level, const char *elem_name, const char *attr_name, const char *attr_value,
Michal Vaskoa63ca342016-02-05 14:29:19 +010030 int close)
31{
32 ly_print(out, "%*s<%s %s=\"%s\"%s>\n", LEVEL, INDENT, elem_name, attr_name, attr_value, (close ? "/" : ""));
33}
34
35static void
Michal Vasko87bb46b2016-02-12 11:51:42 +010036yin_print_close(struct lyout *out, int level, const char *elem_name)
Michal Vaskoa63ca342016-02-05 14:29:19 +010037{
38 ly_print(out, "%*s</%s>\n", LEVEL, INDENT, elem_name);
39}
40
41static void
Michal Vasko87bb46b2016-02-12 11:51:42 +010042yin_print_unsigned(struct lyout *out, int level, const char *elem_name, const char *attr_name, unsigned int attr_value)
Michal Vaskoa63ca342016-02-05 14:29:19 +010043{
44 ly_print(out, "%*s<%s %s=\"%u\"/>\n", LEVEL, INDENT, elem_name, attr_name, attr_value);
45}
46
47static void
48yin_print_text(struct lyout *out, int level, const char *elem_name, const char *text)
49{
50 ly_print(out, "%*s<%s>\n", LEVEL, INDENT, elem_name);
51
52 level++;
53 ly_print(out, "%*s<text>", LEVEL, INDENT);
54 lyxml_dump_text(out, text);
55 ly_print(out, "</text>\n");
56 level--;
57
58 ly_print(out, "%*s</%s>\n", LEVEL, INDENT, elem_name);
59}
60
61static void
Michal Vasko87bb46b2016-02-12 11:51:42 +010062yin_print_restr_sub(struct lyout *out, int level, const struct lys_restr *restr)
Michal Vaskoa63ca342016-02-05 14:29:19 +010063{
64 if (restr->dsc) {
65 yin_print_text(out, level, "description", restr->dsc);
66 }
67 if (restr->ref) {
68 yin_print_text(out, level, "reference", restr->ref);
69 }
70 if (restr->eapptag) {
Michal Vasko87bb46b2016-02-12 11:51:42 +010071 yin_print_open(out, level, "error-app-tag", "value", restr->eapptag, 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +010072 }
73 if (restr->emsg) {
74 ly_print(out, "%*s<error-message>\n", LEVEL, INDENT);
75
76 level++;
77 ly_print(out, "%*s<value>", LEVEL, INDENT, restr->emsg);
78 lyxml_dump_text(out, restr->emsg);
79 ly_print(out, "</value>\n");
80 level--;
81
Michal Vasko87bb46b2016-02-12 11:51:42 +010082 yin_print_close(out, level, "error-message");
Michal Vaskoa63ca342016-02-05 14:29:19 +010083 }
84}
85
86static void
Michal Vasko87bb46b2016-02-12 11:51:42 +010087yin_print_restr(struct lyout *out, int level, const char *elem_name, const struct lys_restr *restr)
Michal Vaskoa63ca342016-02-05 14:29:19 +010088{
89 int close;
90
91 close = (restr->dsc || restr->ref || restr->eapptag || restr->emsg ? 0 : 1);
92
Michal Vasko87bb46b2016-02-12 11:51:42 +010093 yin_print_open(out, level, elem_name, "value", restr->expr, close);
Michal Vaskoa63ca342016-02-05 14:29:19 +010094 if (!close) {
Michal Vasko70983bd2016-05-17 16:14:00 +020095 yin_print_restr_sub(out, level + 1, restr);
Michal Vaskoa63ca342016-02-05 14:29:19 +010096
Michal Vasko87bb46b2016-02-12 11:51:42 +010097 yin_print_close(out, level, elem_name);
Michal Vaskoa63ca342016-02-05 14:29:19 +010098 }
99}
100
101static int
102yin_has_nacmext(const struct lys_node *node)
103{
Michal Vaskodcf98e62016-05-05 17:53:53 +0200104 if (node->nacm && (!lys_parent(node) || lys_parent(node)->nacm != node->nacm)) {
Michal Vaskoa63ca342016-02-05 14:29:19 +0100105 return 1;
106 }
107 return 0;
108}
109
110static void
111yin_print_nacmext(struct lyout *out, int level, const struct lys_node *node, const struct lys_module *module)
112{
113 int i, j;
114 const char *prefix = NULL;
115
Michal Vaskodcf98e62016-05-05 17:53:53 +0200116 if (node->nacm && (!lys_parent(node) || lys_parent(node)->nacm != node->nacm)) {
Michal Vaskoa63ca342016-02-05 14:29:19 +0100117 /* locate ietf-netconf-acm module in imports */
118 if (!strcmp(module->name, "ietf-netconf-acm")) {
119 prefix = module->prefix;
120 } else {
121 /* search in imports */
122 for (i = 0; i < module->imp_size; i++) {
123 if (!strcmp(module->imp[i].module->name, "ietf-netconf-acm")) {
124 prefix = module->imp[i].prefix;
125 break;
126 }
127 }
128 /* and in imports of includes */
129 if (!prefix) {
130 for (j = 0; j < module->inc_size; j++) {
131 for (i = 0; i < module->inc[j].submodule->imp_size; i++) {
132 if (!strcmp(module->inc[j].submodule->imp[i].module->name, "ietf-netconf-acm")) {
133 prefix = module->inc[j].submodule->imp[i].prefix;
134 break;
135 }
136 }
137 }
138 }
139 }
140
Michal Vaskodcf98e62016-05-05 17:53:53 +0200141 if ((node->nacm & LYS_NACM_DENYW) && (!lys_parent(node) || !(lys_parent(node)->nacm & LYS_NACM_DENYW))) {
Michal Vaskoa63ca342016-02-05 14:29:19 +0100142 ly_print(out, "%*s<%s:default-deny-write/>\n", LEVEL, INDENT, prefix);
143 }
Michal Vaskodcf98e62016-05-05 17:53:53 +0200144 if ((node->nacm & LYS_NACM_DENYA) && (!lys_parent(node) || !(lys_parent(node)->nacm & LYS_NACM_DENYA))) {
Michal Vaskoa63ca342016-02-05 14:29:19 +0100145 ly_print(out, "%*s<%s:default-deny-all/>\n", LEVEL, INDENT, prefix);
146 }
147 }
148}
149
150static int
151yin_has_snode_common(const struct lys_node *node)
152{
153 if ((node->flags & LYS_STATUS_MASK) || node->dsc || node->ref) {
154 return 1;
155 }
156 return 0;
157}
158
159/*
160 * Covers:
161 * description, reference, status
162 */
163static void
164yin_print_snode_common(struct lyout *out, int level, const struct lys_node *node)
165{
166 if (node->flags & LYS_STATUS_CURR) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100167 yin_print_open(out, level, "status", "value", "current", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100168 } else if (node->flags & LYS_STATUS_DEPRC) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100169 yin_print_open(out, level, "status", "value", "deprecated", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100170 } else if (node->flags & LYS_STATUS_OBSLT) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100171 yin_print_open(out, level, "status", "value", "obsolete", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100172 }
173
174 if (node->dsc) {
175 yin_print_text(out, level, "description", node->dsc);
176 }
177 if (node->ref) {
178 yin_print_text(out, level, "reference", node->ref);
179 }
180}
181
182static int
183yin_has_snode_common2(const struct lys_node *node)
184{
Michal Vaskodcf98e62016-05-05 17:53:53 +0200185 if ((lys_parent(node) && (lys_parent(node)->flags & LYS_CONFIG_MASK) != (node->flags & LYS_CONFIG_MASK))
186 || (!lys_parent(node) && (node->flags & LYS_CONFIG_R)) || (node->flags & LYS_MAND_MASK)) {
Michal Vaskoa63ca342016-02-05 14:29:19 +0100187 return 1;
188 }
189 return yin_has_snode_common(node);
190}
191
192/*
193 * Covers:
194 * config, mandatory
195 * description, reference, status
196 */
197static void
198yin_print_snode_common2(struct lyout *out, int level, const struct lys_node *node)
199{
Michal Vaskodcf98e62016-05-05 17:53:53 +0200200 if (lys_parent(node)) {
Radek Krejci32c7bd62016-04-14 17:47:04 +0200201 if (node->flags & LYS_CONFIG_SET) {
Michal Vaskoa63ca342016-02-05 14:29:19 +0100202 /* print config when it differs from the parent ... */
203 if (node->flags & LYS_CONFIG_W) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100204 yin_print_open(out, level, "config", "value", "true", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100205 } else if (node->flags & LYS_CONFIG_R) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100206 yin_print_open(out, level, "config", "value", "false", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100207 }
208 }
209 } else if (node->flags & LYS_CONFIG_R) {
210 /* ... or is a top-level state node */
Michal Vasko87bb46b2016-02-12 11:51:42 +0100211 yin_print_open(out, level, "config", "value", "false", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100212 }
213
214 if (node->flags & LYS_MAND_TRUE) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100215 yin_print_open(out, level, "mandatory", "value", "true", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100216 } else if (node->flags & LYS_MAND_FALSE) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100217 yin_print_open(out, level, "mandatory", "value", "false", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100218 }
219
220 yin_print_snode_common(out, level, node);
221}
222
223static void
Radek Krejci9ff0a922016-07-14 13:08:05 +0200224yin_print_iffeature(struct lyout *out, int level, const struct lys_module *module, struct lys_iffeature *iffeature)
Michal Vaskoa63ca342016-02-05 14:29:19 +0100225{
Michal Vaskoa63ca342016-02-05 14:29:19 +0100226 ly_print(out, "%*s<if-feature name=\"", LEVEL, INDENT);
Radek Krejci9ff0a922016-07-14 13:08:05 +0200227 ly_print_iffeature(out, module, iffeature);
228 ly_print(out, "\"/>\n");
Michal Vaskoa63ca342016-02-05 14:29:19 +0100229}
230
231static void
232yin_print_feature(struct lyout *out, int level, const struct lys_feature *feat)
233{
234 int i, close;
235
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200236 close = (yin_has_snode_common((struct lys_node *)feat) || feat->iffeature_size ? 0 : 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100237
Michal Vasko87bb46b2016-02-12 11:51:42 +0100238 yin_print_open(out, level, "feature", "name", feat->name, close);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100239
240 if (!close) {
241 level++;
242 yin_print_snode_common(out, level, (struct lys_node *)feat);
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200243 for (i = 0; i < feat->iffeature_size; ++i) {
Radek Krejci9ff0a922016-07-14 13:08:05 +0200244 yin_print_iffeature(out, level, feat->module, &feat->iffeature[i]);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100245 }
246 level--;
247
Michal Vasko87bb46b2016-02-12 11:51:42 +0100248 yin_print_close(out, level, "feature");
Michal Vaskoa63ca342016-02-05 14:29:19 +0100249 }
250}
251
252static void
253yin_print_when(struct lyout *out, int level, const struct lys_module *module, const struct lys_when *when)
254{
255 int close;
256 const char *str;
257
258 close = (when->dsc || when->ref ? 0 : 1);
259
260 str = transform_json2schema(module, when->cond);
261 if (!str) {
262 ly_print(out, "(!error!)");
263 return;
264 }
265
266 ly_print(out, "%*s<when condition=\"", LEVEL, INDENT);
267 lyxml_dump_text(out, str);
268 ly_print(out, "\"%s>\n", (close ? "/" : ""));
269
270 lydict_remove(module->ctx, str);
271
272 if (!close) {
273 level++;
274 if (when->dsc) {
275 yin_print_text(out, level, "description", when->dsc);
276 }
277 if (when->ref) {
278 yin_print_text(out, level, "reference", when->ref);
279 }
280 level--;
281
Michal Vasko87bb46b2016-02-12 11:51:42 +0100282 yin_print_close(out, level, "when");
Michal Vaskoa63ca342016-02-05 14:29:19 +0100283 }
284}
285
286static void
287yin_print_type(struct lyout *out, int level, const struct lys_module *module, const struct lys_type *type)
288{
Michal Vasko3f053ef2016-02-12 14:27:13 +0100289 int i, close, close2;
Michal Vaskoa63ca342016-02-05 14:29:19 +0100290 const char *str;
291 struct lys_module *mod;
292
Michal Vasko4634cda2016-02-16 09:22:09 +0100293 /* decide whether the type will have any substatements */
294 close = 1;
Michal Vaskoa63ca342016-02-05 14:29:19 +0100295 switch (type->base) {
296 case LY_TYPE_BINARY:
Michal Vaskoa63ca342016-02-05 14:29:19 +0100297 if (type->info.binary.length) {
298 close = 0;
299 }
300 break;
301 case LY_TYPE_DEC64:
Michal Vasko4634cda2016-02-16 09:22:09 +0100302 if (type->info.dec64.dig || type->info.dec64.range) {
303 close = 0;
304 }
305 break;
Michal Vaskoa63ca342016-02-05 14:29:19 +0100306 case LY_TYPE_ENUM:
Michal Vasko4634cda2016-02-16 09:22:09 +0100307 if (type->info.enums.count) {
308 close = 0;
309 }
310 break;
Michal Vaskoa63ca342016-02-05 14:29:19 +0100311 case LY_TYPE_IDENT:
Michal Vasko4634cda2016-02-16 09:22:09 +0100312 if (type->info.ident.ref) {
313 close = 0;
314 }
315 break;
Michal Vaskoa63ca342016-02-05 14:29:19 +0100316 case LY_TYPE_BITS:
Michal Vasko4634cda2016-02-16 09:22:09 +0100317 if (type->info.bits.count) {
318 close = 0;
319 }
320 break;
Michal Vaskoa63ca342016-02-05 14:29:19 +0100321 case LY_TYPE_UNION:
Michal Vasko4634cda2016-02-16 09:22:09 +0100322 if (type->info.uni.count) {
323 close = 0;
324 }
325 break;
Michal Vaskoa63ca342016-02-05 14:29:19 +0100326 case LY_TYPE_LEAFREF:
Radek Krejci0dbff6a2016-07-17 12:40:18 +0200327 if (ly_strequal(type->der->name, "leafref", 0)) {
Michal Vasko4634cda2016-02-16 09:22:09 +0100328 close = 0;
329 }
Michal Vaskoa63ca342016-02-05 14:29:19 +0100330 break;
331 case LY_TYPE_INST:
Michal Vaskoa63ca342016-02-05 14:29:19 +0100332 if (type->info.inst.req) {
333 close = 0;
334 }
335 break;
336 case LY_TYPE_INT8:
337 case LY_TYPE_INT16:
338 case LY_TYPE_INT32:
339 case LY_TYPE_INT64:
340 case LY_TYPE_UINT8:
341 case LY_TYPE_UINT16:
342 case LY_TYPE_UINT32:
343 case LY_TYPE_UINT64:
Michal Vaskoa63ca342016-02-05 14:29:19 +0100344 if (type->info.num.range) {
345 close = 0;
346 }
347 break;
348 case LY_TYPE_STRING:
Michal Vaskoa63ca342016-02-05 14:29:19 +0100349 if (type->info.str.length || type->info.str.pat_count) {
350 close = 0;
351 }
352 break;
353 default:
Michal Vaskoa63ca342016-02-05 14:29:19 +0100354 break;
355 }
356
357 if (type->module_name) {
358 ly_print(out, "%*s<type name=\"%s:%s\"%s>\n", LEVEL, INDENT,
359 transform_module_name2import_prefix(module, type->module_name), type->der->name, (close ? "/" : ""));
360 } else {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100361 yin_print_open(out, level, "type", "name", type->der->name, close);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100362 }
363
364 if (!close) {
365 level++;
366 switch (type->base) {
367 case LY_TYPE_BINARY:
368 if (type->info.binary.length) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100369 yin_print_restr(out, level, "length", type->info.binary.length);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100370 }
371 break;
372 case LY_TYPE_BITS:
373 for (i = 0; i < type->info.bits.count; ++i) {
Michal Vasko3f053ef2016-02-12 14:27:13 +0100374 close2 = !yin_has_snode_common((struct lys_node *)&type->info.bits.bit[i])
375 && (type->info.bits.bit[i].flags & LYS_AUTOASSIGNED);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100376
Michal Vasko3f053ef2016-02-12 14:27:13 +0100377 yin_print_open(out, level, "bit", "name", type->info.bits.bit[i].name, close2);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100378
Michal Vasko3f053ef2016-02-12 14:27:13 +0100379 if (!close2) {
380 level++;
381 yin_print_snode_common(out, level, (struct lys_node *)&type->info.bits.bit[i]);
382 if (!(type->info.bits.bit[i].flags & LYS_AUTOASSIGNED)) {
383 yin_print_unsigned(out, level, "position", "value", type->info.bits.bit[i].pos);
384 }
385 level--;
386
387 yin_print_close(out, level, "bit");
388 }
Michal Vaskoa63ca342016-02-05 14:29:19 +0100389 }
390 break;
391 case LY_TYPE_DEC64:
Michal Vasko4634cda2016-02-16 09:22:09 +0100392 if (type->info.dec64.dig) {
393 yin_print_unsigned(out, level, "fraction-digits", "value", type->info.dec64.dig);
394 }
Michal Vaskoa63ca342016-02-05 14:29:19 +0100395 if (type->info.dec64.range) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100396 yin_print_restr(out, level, "range", type->info.dec64.range);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100397 }
398 break;
399 case LY_TYPE_ENUM:
400 for (i = 0; i < type->info.enums.count; i++) {
Michal Vasko3f053ef2016-02-12 14:27:13 +0100401 close2 = !yin_has_snode_common((struct lys_node *)&type->info.enums.enm[i])
402 && (type->info.enums.enm[i].flags & LYS_AUTOASSIGNED);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100403
Michal Vasko3f053ef2016-02-12 14:27:13 +0100404 yin_print_open(out, level, "enum", "name", type->info.enums.enm[i].name, close2);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100405
Michal Vasko3f053ef2016-02-12 14:27:13 +0100406 if (!close2) {
407 level++;
408 yin_print_snode_common(out, level, (struct lys_node *)&type->info.enums.enm[i]);
409 if (!(type->info.enums.enm[i].flags & LYS_AUTOASSIGNED)) {
410 ly_print(out, "%*s<value value=\"%d\"/>\n", LEVEL, INDENT, type->info.enums.enm[i].value);
411 }
412 level--;
413
414 yin_print_close(out, level, "enum");
415 }
Michal Vaskoa63ca342016-02-05 14:29:19 +0100416 }
417 break;
418 case LY_TYPE_IDENT:
Michal Vasko4634cda2016-02-16 09:22:09 +0100419 if (type->info.ident.ref) {
Radek Krejcic4283442016-04-22 09:19:27 +0200420 mod = lys_main_module(type->info.ident.ref->module);
421 if (lys_main_module(module) == mod) {
Michal Vasko4634cda2016-02-16 09:22:09 +0100422 ly_print(out, "%*s<base name=\"%s\"/>\n", LEVEL, INDENT, type->info.ident.ref->name);
423 } else {
424 ly_print(out, "%*s<base name=\"%s:%s\"/>\n", LEVEL, INDENT,
425 transform_module_name2import_prefix(module, mod->name), type->info.ident.ref->name);
426 }
Michal Vaskoa63ca342016-02-05 14:29:19 +0100427 }
428 break;
429 case LY_TYPE_INST:
430 if (type->info.inst.req == 1) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100431 yin_print_open(out, level, "require-instance", "value", "true", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100432 } else if (type->info.inst.req == -1) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100433 yin_print_open(out, level, "require-instance", "value", "false", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100434 }
435 break;
436 case LY_TYPE_INT8:
437 case LY_TYPE_INT16:
438 case LY_TYPE_INT32:
439 case LY_TYPE_INT64:
440 case LY_TYPE_UINT8:
441 case LY_TYPE_UINT16:
442 case LY_TYPE_UINT32:
443 case LY_TYPE_UINT64:
444 if (type->info.num.range) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100445 yin_print_restr(out, level, "range", type->info.num.range);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100446 }
447 break;
448 case LY_TYPE_LEAFREF:
Michal Vasko4634cda2016-02-16 09:22:09 +0100449 if (type->info.lref.path) {
450 str = transform_json2schema(module, type->info.lref.path);
451 yin_print_open(out, level, "path", "value", str, 1);
452 lydict_remove(module->ctx, str);
453 }
Michal Vaskoa63ca342016-02-05 14:29:19 +0100454 break;
455 case LY_TYPE_STRING:
456 if (type->info.str.length) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100457 yin_print_restr(out, level, "length", type->info.str.length);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100458 }
459 for (i = 0; i < type->info.str.pat_count; i++) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100460 yin_print_restr(out, level, "pattern", &type->info.str.patterns[i]);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100461 }
462 break;
463 case LY_TYPE_UNION:
464 for (i = 0; i < type->info.uni.count; ++i) {
465 yin_print_type(out, level, module, &type->info.uni.types[i]);
466 }
467 break;
468 default:
469 /* other types do not have substatements */
470 break;
471 }
472 level--;
473
Michal Vasko87bb46b2016-02-12 11:51:42 +0100474 yin_print_close(out, level, "type");
Michal Vaskoa63ca342016-02-05 14:29:19 +0100475 }
476}
477
478static void
479yin_print_must(struct lyout *out, int level, const struct lys_module *module, const struct lys_restr *must)
480{
481 const char *str;
482 int close;
483
484 close = (must->dsc || must->ref || must->eapptag || must->emsg ? 0 : 1);
485
486 str = transform_json2schema(module, must->expr);
487 if (!str) {
488 ly_print(out, "(!error!)");
489 return;
490 }
491
492 ly_print(out, "%*s<must condition=\"", LEVEL, INDENT);
493 lyxml_dump_text(out, str);
494 ly_print(out, "\"%s>\n", (close ? "/" : ""));
495
496 lydict_remove(module->ctx, str);
497
498 if (!close) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100499 yin_print_restr_sub(out, level + 1, must);
500 yin_print_close(out, level, "must");
Michal Vaskoa63ca342016-02-05 14:29:19 +0100501 }
502}
503
504static void
505yin_print_unique(struct lyout *out, int level, const struct lys_unique *uniq)
506{
507 int i;
508
509 ly_print(out, "%*s<unique tag=\"", LEVEL, INDENT);
510 for (i = 0; i < uniq->expr_size; i++) {
511 ly_print(out, "%s%s", uniq->expr[i], i + 1 < uniq->expr_size ? " " : "");
512 }
513 ly_print(out, "\"/>\n");
514}
515
516static void
517yin_print_refine(struct lyout *out, int level, const struct lys_module *module, const struct lys_refine *refine)
518{
519 int i;
520 const char *str;
521
522 str = transform_json2xml(module, refine->target_name, NULL, NULL, NULL);
Michal Vasko87bb46b2016-02-12 11:51:42 +0100523 yin_print_open(out, level, "refine", "target-node", str, 0);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100524 lydict_remove(module->ctx, str);
525
526 level++;
527 if (refine->flags & LYS_CONFIG_W) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100528 yin_print_open(out, level, "config", "value", "true", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100529 } else if (refine->flags & LYS_CONFIG_R) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100530 yin_print_open(out, level, "config", "value", "false", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100531 }
532
533 if (refine->flags & LYS_MAND_TRUE) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100534 yin_print_open(out, level, "mandatory", "value", "true", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100535 } else if (refine->flags & LYS_MAND_FALSE) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100536 yin_print_open(out, level, "mandatory", "value", "false", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100537 }
538
539 yin_print_snode_common(out, level, (struct lys_node *)refine);
540
541 for (i = 0; i < refine->must_size; ++i) {
542 yin_print_must(out, level, module, &refine->must[i]);
543 }
Radek Krejcibf06c4f2016-07-29 15:49:56 +0200544 for (i = 0; i < refine->iffeature_size; i++) {
545 yin_print_iffeature(out, level, module, &refine->iffeature[i]);
546 }
Michal Vaskoa63ca342016-02-05 14:29:19 +0100547
548 if (refine->target_type & (LYS_LEAF | LYS_CHOICE)) {
549 if (refine->mod.dflt) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100550 yin_print_open(out, level, "default", "value", refine->mod.dflt, 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100551 }
552 } else if (refine->target_type == LYS_CONTAINER) {
553 if (refine->mod.presence) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100554 yin_print_open(out, level, "presence", "value", refine->mod.presence, 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100555 }
556 } else if (refine->target_type & (LYS_LIST | LYS_LEAFLIST)) {
Radek Krejci0f04a6c2016-04-14 16:16:36 +0200557 if (refine->flags & LYS_RFN_MINSET) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100558 yin_print_unsigned(out, level, "min-elements", "value", refine->mod.list.min);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100559 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +0200560 if (refine->flags & LYS_RFN_MAXSET) {
Radek Krejci0d7b2472016-02-12 11:11:03 +0100561 if (refine->mod.list.max) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100562 yin_print_unsigned(out, level, "max-elements", "value", refine->mod.list.max);
Radek Krejci0d7b2472016-02-12 11:11:03 +0100563 } else {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100564 yin_print_open(out, level, "max-elements", "value", "unbounded", 1);
Radek Krejci0d7b2472016-02-12 11:11:03 +0100565 }
Michal Vaskoa63ca342016-02-05 14:29:19 +0100566 }
567 }
568 level--;
569
Michal Vasko87bb46b2016-02-12 11:51:42 +0100570 yin_print_close(out, level, "refine");
Michal Vaskoa63ca342016-02-05 14:29:19 +0100571}
572
573static void
574yin_print_deviation(struct lyout *out, int level, const struct lys_module *module,
575 const struct lys_deviation *deviation)
576{
577 int i, j;
578 const char *str;
579
Michal Vasko5d112852016-02-12 16:47:13 +0100580 str = transform_json2schema(module, deviation->target_name);
Michal Vasko87bb46b2016-02-12 11:51:42 +0100581 yin_print_open(out, level, "deviation", "target-node", str, 0);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100582 lydict_remove(module->ctx, str);
583
584 level++;
585 if (deviation->dsc) {
586 yin_print_text(out, level, "description", deviation->dsc);
587 }
588 if (deviation->ref) {
589 yin_print_text(out, level, "reference", deviation->ref);
590 }
591
592 for (i = 0; i < deviation->deviate_size; ++i) {
593 ly_print(out, "%*s<deviate value=", LEVEL, INDENT);
594 if (deviation->deviate[i].mod == LY_DEVIATE_NO) {
Michal Vaskod875e882016-05-19 10:57:30 +0200595 ly_print(out, "\"not-supported\"/>\n");
596 continue;
Michal Vaskoa63ca342016-02-05 14:29:19 +0100597 } else if (deviation->deviate[i].mod == LY_DEVIATE_ADD) {
598 ly_print(out, "\"add\">\n");
599 } else if (deviation->deviate[i].mod == LY_DEVIATE_RPL) {
600 ly_print(out, "\"replace\">\n");
601 } else if (deviation->deviate[i].mod == LY_DEVIATE_DEL) {
602 ly_print(out, "\"delete\">\n");
603 }
604
605 level++;
606 if (deviation->deviate[i].flags & LYS_CONFIG_W) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100607 yin_print_open(out, level, "config", "value", "true", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100608 } else if (deviation->deviate[i].flags & LYS_CONFIG_R) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100609 yin_print_open(out, level, "config", "value", "false", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100610 }
611
612 if (deviation->deviate[i].flags & LYS_MAND_TRUE) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100613 yin_print_open(out, level, "mandatory", "value", "true", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100614 } else if (deviation->deviate[i].flags & LYS_MAND_FALSE) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100615 yin_print_open(out, level, "mandatory", "value", "false", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100616 }
617
618 if (deviation->deviate[i].dflt) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100619 yin_print_open(out, level, "default", "value", deviation->deviate[i].dflt, 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100620 }
621
Radek Krejci0d7b2472016-02-12 11:11:03 +0100622 if (deviation->deviate[i].min_set) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100623 yin_print_unsigned(out, level, "min-elements", "value", deviation->deviate[i].min);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100624 }
Radek Krejci0d7b2472016-02-12 11:11:03 +0100625 if (deviation->deviate[i].max_set) {
Michal Vasko87ea6cb2016-05-19 10:58:01 +0200626 if (deviation->deviate[i].max) {
627 yin_print_unsigned(out, level, "max-elements", "value", deviation->deviate[i].max);
Radek Krejci0d7b2472016-02-12 11:11:03 +0100628 } else {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100629 yin_print_open(out, level, "max-elements", "value", "unbounded", 1);
Radek Krejci0d7b2472016-02-12 11:11:03 +0100630 }
Michal Vaskoa63ca342016-02-05 14:29:19 +0100631 }
632
633 for (j = 0; j < deviation->deviate[i].must_size; ++j) {
634 yin_print_must(out, level, module, &deviation->deviate[i].must[j]);
635 }
636
637 for (j = 0; j < deviation->deviate[i].unique_size; ++j) {
638 yin_print_unique(out, level, &deviation->deviate[i].unique[j]);
639 }
640
641 if (deviation->deviate[i].type) {
642 yin_print_type(out, level, module, deviation->deviate[i].type);
643 }
644
645 if (deviation->deviate[i].units) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100646 yin_print_open(out, level, "units", "name", deviation->deviate[i].units, 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100647 }
648 level--;
649
Michal Vasko87bb46b2016-02-12 11:51:42 +0100650 yin_print_close(out, level, "deviate");
Michal Vaskoa63ca342016-02-05 14:29:19 +0100651 }
652 level--;
653
Michal Vasko87bb46b2016-02-12 11:51:42 +0100654 yin_print_close(out, level, "deviation");
Michal Vaskoa63ca342016-02-05 14:29:19 +0100655}
656
657static void
658yin_print_augment(struct lyout *out, int level, const struct lys_module *module,
659 const struct lys_node_augment *augment)
660{
661 int i;
662 struct lys_node *sub;
663 const char *str;
664
Michal Vasko5d112852016-02-12 16:47:13 +0100665 str = transform_json2schema(module, augment->target_name);
Michal Vasko87bb46b2016-02-12 11:51:42 +0100666 yin_print_open(out, level, "augment", "target-node", str, 0);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100667 lydict_remove(module->ctx, str);
668
669 level++;
670 yin_print_nacmext(out, level, (struct lys_node *)augment, module);
671 yin_print_snode_common(out, level, (struct lys_node *)augment);
672
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200673 for (i = 0; i < augment->iffeature_size; i++) {
Radek Krejci9ff0a922016-07-14 13:08:05 +0200674 yin_print_iffeature(out, level, module, &augment->iffeature[i]);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100675 }
676
677 if (augment->when) {
678 yin_print_when(out, level, module, augment->when);
679 }
680
681 LY_TREE_FOR(augment->child, sub) {
Michal Vasko0c5e9282016-02-15 13:11:57 +0100682 /* only our augment */
683 if (sub->parent != (struct lys_node *)augment) {
684 continue;
685 }
Michal Vaskoa63ca342016-02-05 14:29:19 +0100686 yin_print_snode(out, level, sub,
687 LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200688 LYS_USES | LYS_ANYXML | LYS_CASE | LYS_ACTION);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100689 }
690 level--;
691
Michal Vasko87bb46b2016-02-12 11:51:42 +0100692 yin_print_close(out, level, "augment");
Michal Vaskoa63ca342016-02-05 14:29:19 +0100693}
694
695static void
696yin_print_typedef(struct lyout *out, int level, const struct lys_module *module, const struct lys_tpdf *tpdf)
697{
Michal Vasko87bb46b2016-02-12 11:51:42 +0100698 yin_print_open(out, level, "typedef", "name", tpdf->name, 0);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100699
700 level++;
701 yin_print_snode_common(out, level, (struct lys_node *)tpdf);
702 yin_print_type(out, level, module, &tpdf->type);
703 if (tpdf->units) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100704 yin_print_open(out, level, "units", "name", tpdf->units, 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100705 }
706 if (tpdf->dflt) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100707 yin_print_open(out, level, "default", "value", tpdf->dflt, 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100708 }
709 level--;
710
Michal Vasko87bb46b2016-02-12 11:51:42 +0100711 yin_print_close(out, level, "typedef");
Michal Vaskoa63ca342016-02-05 14:29:19 +0100712}
713
714static void
715yin_print_identity(struct lyout *out, int level, const struct lys_ident *ident)
716{
Radek Krejci018f1f52016-08-03 16:01:20 +0200717 int close, i;
Michal Vasko6c629ac2016-02-15 14:08:23 +0100718 struct lys_module *mod;
Michal Vaskoa63ca342016-02-05 14:29:19 +0100719
720 close = (yin_has_snode_common((struct lys_node *)ident) || ident->base ? 0 : 1);
721
Michal Vasko87bb46b2016-02-12 11:51:42 +0100722 yin_print_open(out, level, "identity", "name", ident->name, close);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100723
724 if (!close) {
725 level++;
726 yin_print_snode_common(out, level, (struct lys_node *)ident);
Radek Krejci018f1f52016-08-03 16:01:20 +0200727 for (i = 0; i < ident->base_size; i++) {
Michal Vaskoa63ca342016-02-05 14:29:19 +0100728 ly_print(out, "%*s<base name=\"", LEVEL, INDENT);
Radek Krejci018f1f52016-08-03 16:01:20 +0200729 mod = lys_main_module(ident->base[i]->module);
Radek Krejcic4283442016-04-22 09:19:27 +0200730 if (lys_main_module(ident->module) != mod) {
Michal Vaskoa63ca342016-02-05 14:29:19 +0100731 ly_print(out, "%s:", transform_module_name2import_prefix(ident->module, mod->name));
732 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200733 ly_print(out, "%s\"/>\n", ident->base[i]->name);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100734 }
735 level--;
736
Michal Vasko87bb46b2016-02-12 11:51:42 +0100737 yin_print_close(out, level, "identity");
Michal Vaskoa63ca342016-02-05 14:29:19 +0100738 }
739}
740
741static void
742yin_print_container(struct lyout *out, int level, const struct lys_node *node)
743{
744 int i;
745 struct lys_node *sub;
746 struct lys_node_container *cont = (struct lys_node_container *)node;
747
Michal Vasko87bb46b2016-02-12 11:51:42 +0100748 yin_print_open(out, level, "container", "name", node->name, 0);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100749
750 level++;
751 yin_print_nacmext(out, level, node, node->module);
752
753 if (cont->when) {
754 yin_print_when(out, level, node->module, cont->when);
755 }
756
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200757 for (i = 0; i < cont->iffeature_size; i++) {
Radek Krejci9ff0a922016-07-14 13:08:05 +0200758 yin_print_iffeature(out, level, node->module, &cont->iffeature[i]);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100759 }
760
761 for (i = 0; i < cont->must_size; i++) {
762 yin_print_must(out, level, node->module, &cont->must[i]);
763 }
764
765 if (cont->presence) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100766 yin_print_open(out, level, "presence", "value", cont->presence, 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100767 }
768
769 yin_print_snode_common2(out, level, node);
770
771 for (i = 0; i < cont->tpdf_size; i++) {
772 yin_print_typedef(out, level, node->module, &cont->tpdf[i]);
773 }
774
775 LY_TREE_FOR(node->child, sub) {
Michal Vasko0c5e9282016-02-15 13:11:57 +0100776 /* augments */
777 if (sub->parent != node) {
Michal Vaskoa63ca342016-02-05 14:29:19 +0100778 continue;
779 }
780 yin_print_snode(out, level, sub,
781 LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
Michal Vaskoca7cbc42016-07-01 11:36:53 +0200782 LYS_USES | LYS_GROUPING | LYS_ANYXML | LYS_ACTION);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100783 }
784 level--;
785
Michal Vasko87bb46b2016-02-12 11:51:42 +0100786 yin_print_close(out, level, "container");
Michal Vaskoa63ca342016-02-05 14:29:19 +0100787}
788
789static void
790yin_print_case(struct lyout *out, int level, const struct lys_node *node)
791{
792 int i;
793 struct lys_node *sub;
794 struct lys_node_case *cas = (struct lys_node_case *)node;
795
Michal Vasko87bb46b2016-02-12 11:51:42 +0100796 yin_print_open(out, level, "case", "name", cas->name, 0);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100797
798 level++;
799 yin_print_nacmext(out, level, node, node->module);
800 yin_print_snode_common2(out, level, node);
801
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200802 for (i = 0; i < cas->iffeature_size; i++) {
Radek Krejci9ff0a922016-07-14 13:08:05 +0200803 yin_print_iffeature(out, level, node->module, &cas->iffeature[i]);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100804 }
805
806 if (cas->when) {
807 yin_print_when(out, level, node->module, cas->when);
808 }
809
810 LY_TREE_FOR(node->child, sub) {
Michal Vasko0c5e9282016-02-15 13:11:57 +0100811 /* augments */
812 if (sub->parent != node) {
Michal Vaskoa63ca342016-02-05 14:29:19 +0100813 continue;
814 }
815 yin_print_snode(out, level, sub,
816 LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
817 LYS_USES | LYS_ANYXML);
818 }
819 level--;
820
Michal Vasko87bb46b2016-02-12 11:51:42 +0100821 yin_print_close(out, level, "case");
Michal Vaskoa63ca342016-02-05 14:29:19 +0100822}
823
824static void
825yin_print_choice(struct lyout *out, int level, const struct lys_node *node)
826{
827 int i;
828 struct lys_node *sub;
829 struct lys_node_choice *choice = (struct lys_node_choice *)node;
830
Michal Vasko87bb46b2016-02-12 11:51:42 +0100831 yin_print_open(out, level, "choice", "name", node->name, 0);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100832
833 level++;
834 yin_print_nacmext(out, level, node, node->module);
835 if (choice->dflt) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100836 yin_print_open(out, level, "default", "value", choice->dflt->name, 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100837 }
838
839 yin_print_snode_common2(out, level, node);
840
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200841 for (i = 0; i < choice->iffeature_size; i++) {
Radek Krejci9ff0a922016-07-14 13:08:05 +0200842 yin_print_iffeature(out, level, node->module, &choice->iffeature[i]);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100843 }
844
845 if (choice->when) {
846 yin_print_when(out, level, node->module, choice->when);
847 }
848
849 LY_TREE_FOR(node->child, sub) {
Michal Vasko0c5e9282016-02-15 13:11:57 +0100850 /* augments */
851 if (sub->parent != node) {
852 continue;
Michal Vaskoa63ca342016-02-05 14:29:19 +0100853 }
854 yin_print_snode(out, level, sub,
855 LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYXML | LYS_CASE);
856 }
857 level--;
858
Michal Vasko87bb46b2016-02-12 11:51:42 +0100859 yin_print_close(out, level, "choice");
Michal Vaskoa63ca342016-02-05 14:29:19 +0100860}
861
862static void
863yin_print_leaf(struct lyout *out, int level, const struct lys_node *node)
864{
865 int i;
866 struct lys_node_leaf *leaf = (struct lys_node_leaf *)node;
867
Michal Vasko87bb46b2016-02-12 11:51:42 +0100868 yin_print_open(out, level, "leaf", "name", node->name, 0);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100869
870 level++;
871 yin_print_nacmext(out, level, node, node->module);
872 if (leaf->when) {
873 yin_print_when(out, level, node->module, leaf->when);
874 }
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200875 for (i = 0; i < leaf->iffeature_size; i++) {
Radek Krejci9ff0a922016-07-14 13:08:05 +0200876 yin_print_iffeature(out, level, node->module, &leaf->iffeature[i]);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100877 }
878 for (i = 0; i < leaf->must_size; i++) {
879 yin_print_must(out, level, node->module, &leaf->must[i]);
880 }
881 yin_print_snode_common2(out, level, node);
882 yin_print_type(out, level, node->module, &leaf->type);
883 if (leaf->units) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100884 yin_print_open(out, level, "units", "name", leaf->units, 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100885 }
886 if (leaf->dflt) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100887 yin_print_open(out, level, "default", "value", leaf->dflt, 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100888 }
889 level--;
890
Michal Vasko87bb46b2016-02-12 11:51:42 +0100891 yin_print_close(out, level, "leaf");
Michal Vaskoa63ca342016-02-05 14:29:19 +0100892}
893
894static void
895yin_print_anyxml(struct lyout *out, int level, const struct lys_node *node)
896{
897 int i, close;
898 struct lys_node_anyxml *anyxml = (struct lys_node_anyxml *)node;
899
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200900 close = (yin_has_nacmext(node) || yin_has_snode_common2(node) || anyxml->iffeature_size || anyxml->must_size
Michal Vaskoa63ca342016-02-05 14:29:19 +0100901 || anyxml->when ? 0 : 1);
902
Michal Vasko87bb46b2016-02-12 11:51:42 +0100903 yin_print_open(out, level, "anyxml", "name", anyxml->name, close);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100904
905 if (!close) {
906 level++;
907 yin_print_nacmext(out, level, node, node->module);
908 yin_print_snode_common2(out, level, node);
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200909 for (i = 0; i < anyxml->iffeature_size; i++) {
Radek Krejci9ff0a922016-07-14 13:08:05 +0200910 yin_print_iffeature(out, level, node->module, &anyxml->iffeature[i]);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100911 }
912 for (i = 0; i < anyxml->must_size; i++) {
913 yin_print_must(out, level, node->module, &anyxml->must[i]);
914 }
915 if (anyxml->when) {
916 yin_print_when(out, level, node->module, anyxml->when);
917 }
918 level--;
919
Michal Vasko87bb46b2016-02-12 11:51:42 +0100920 yin_print_close(out, level, "anyxml");
Michal Vaskoa63ca342016-02-05 14:29:19 +0100921 }
922}
923
924static void
925yin_print_leaflist(struct lyout *out, int level, const struct lys_node *node)
926{
927 int i;
928 struct lys_node_leaflist *llist = (struct lys_node_leaflist *)node;
929
Michal Vasko87bb46b2016-02-12 11:51:42 +0100930 yin_print_open(out, level, "leaf-list", "name", node->name, 0);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100931
932 level++;
933 yin_print_nacmext(out, level, node, node->module);
934 if (llist->when) {
935 yin_print_when(out, level, llist->module, llist->when);
936 }
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200937 for (i = 0; i < llist->iffeature_size; i++) {
Radek Krejci9ff0a922016-07-14 13:08:05 +0200938 yin_print_iffeature(out, level, node->module, &llist->iffeature[i]);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100939 }
940 for (i = 0; i < llist->must_size; i++) {
941 yin_print_must(out, level, node->module, &llist->must[i]);
942 }
943 yin_print_snode_common2(out, level, node);
944 yin_print_type(out, level, node->module, &llist->type);
945 if (llist->units) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100946 yin_print_open(out, level, "units", "name", llist->units, 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100947 }
948 if (llist->min > 0) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100949 yin_print_unsigned(out, level, "min-elements", "value", llist->min);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100950 }
951 if (llist->max > 0) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100952 yin_print_unsigned(out, level, "max-elements", "value", llist->max);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100953 }
954 if (llist->flags & LYS_USERORDERED) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100955 yin_print_open(out, level, "ordered-by", "value", "user", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100956 }
957 level--;
958
Michal Vasko87bb46b2016-02-12 11:51:42 +0100959 yin_print_close(out, level, "leaf-list");
Michal Vaskoa63ca342016-02-05 14:29:19 +0100960}
961
962static void
963yin_print_list(struct lyout *out, int level, const struct lys_node *node)
964{
965 int i;
966 struct lys_node *sub;
967 struct lys_node_list *list = (struct lys_node_list *)node;
968
Michal Vasko87bb46b2016-02-12 11:51:42 +0100969 yin_print_open(out, level, "list", "name", node->name, 0);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100970
971 level++;
972 yin_print_nacmext(out, level, node, node->module);
973 if (list->when) {
974 yin_print_when(out, level, list->module, list->when);
975 }
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200976 for (i = 0; i < list->iffeature_size; i++) {
Radek Krejci9ff0a922016-07-14 13:08:05 +0200977 yin_print_iffeature(out, level, node->module, &list->iffeature[i]);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100978 }
979 for (i = 0; i < list->must_size; i++) {
980 yin_print_must(out, level, list->module, &list->must[i]);
981 }
982 if (list->keys_size) {
983 ly_print(out, "%*s<key value=\"", LEVEL, INDENT);
984 for (i = 0; i < list->keys_size; i++) {
985 ly_print(out, "%s%s", list->keys[i]->name, i + 1 < list->keys_size ? " " : "");
986 }
987 ly_print(out, "\"/>\n");
988 }
989 for (i = 0; i < list->unique_size; i++) {
990 yin_print_unique(out, level, &list->unique[i]);
991 }
992 yin_print_snode_common2(out, level, node);
993 if (list->min > 0) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100994 yin_print_unsigned(out, level, "min-elements", "value", list->min);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100995 }
996 if (list->max > 0) {
Michal Vasko87bb46b2016-02-12 11:51:42 +0100997 yin_print_unsigned(out, level, "max-elements", "value", list->max);
Michal Vaskoa63ca342016-02-05 14:29:19 +0100998 }
999 if (list->flags & LYS_USERORDERED) {
Michal Vasko87bb46b2016-02-12 11:51:42 +01001000 yin_print_open(out, level, "ordered-by", "value", "user", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001001 }
1002
1003 for (i = 0; i < list->tpdf_size; i++) {
1004 yin_print_typedef(out, level, list->module, &list->tpdf[i]);
1005 }
1006 LY_TREE_FOR(node->child, sub) {
Michal Vasko0c5e9282016-02-15 13:11:57 +01001007 /* augments */
1008 if (sub->parent != node) {
Michal Vaskoa63ca342016-02-05 14:29:19 +01001009 continue;
1010 }
1011 yin_print_snode(out, level, sub,
1012 LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
Michal Vaskoca7cbc42016-07-01 11:36:53 +02001013 LYS_USES | LYS_GROUPING | LYS_ANYXML | LYS_ACTION);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001014 }
1015 level--;
1016
Michal Vasko87bb46b2016-02-12 11:51:42 +01001017 yin_print_close(out, level, "list");
Michal Vaskoa63ca342016-02-05 14:29:19 +01001018}
1019
1020static void
1021yin_print_grouping(struct lyout *out, int level, const struct lys_node *node)
1022{
1023 int i;
Michal Vasko0c5e9282016-02-15 13:11:57 +01001024 struct lys_node *sub;
Michal Vaskoa63ca342016-02-05 14:29:19 +01001025 struct lys_node_grp *grp = (struct lys_node_grp *)node;
1026
Michal Vasko87bb46b2016-02-12 11:51:42 +01001027 yin_print_open(out, level, "grouping", "name", node->name, 0);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001028
1029 level++;
1030 yin_print_snode_common(out, level, node);
1031
1032 for (i = 0; i < grp->tpdf_size; i++) {
1033 yin_print_typedef(out, level, node->module, &grp->tpdf[i]);
1034 }
1035
Michal Vasko0c5e9282016-02-15 13:11:57 +01001036 LY_TREE_FOR(node->child, sub) {
1037 yin_print_snode(out, level, sub,
Michal Vaskoa63ca342016-02-05 14:29:19 +01001038 LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
Michal Vaskoca7cbc42016-07-01 11:36:53 +02001039 LYS_USES | LYS_GROUPING | LYS_ANYXML | LYS_ACTION);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001040 }
1041 level--;
1042
Michal Vasko87bb46b2016-02-12 11:51:42 +01001043 yin_print_close(out, level, "grouping");
Michal Vaskoa63ca342016-02-05 14:29:19 +01001044}
1045
1046static void
1047yin_print_uses(struct lyout *out, int level, const struct lys_node *node)
1048{
1049 int i, close;
1050 struct lys_node_uses *uses = (struct lys_node_uses *)node;
Michal Vasko6c629ac2016-02-15 14:08:23 +01001051 struct lys_module *mod;
Michal Vaskoa63ca342016-02-05 14:29:19 +01001052
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001053 close = (yin_has_nacmext(node) || yin_has_snode_common(node) || uses->iffeature_size || uses->when
Michal Vaskoa63ca342016-02-05 14:29:19 +01001054 || uses->refine_size || uses->augment_size ? 0 : 1);
1055
1056 ly_print(out, "%*s<uses name=\"", LEVEL, INDENT);
1057 if (node->child) {
Michal Vasko6c629ac2016-02-15 14:08:23 +01001058 mod = lys_node_module(node->child);
Michal Vasko1dae8ec2016-02-15 14:49:01 +01001059 if (lys_node_module(node) != mod) {
Michal Vaskoa63ca342016-02-05 14:29:19 +01001060 ly_print(out, "%s:", transform_module_name2import_prefix(node->module, mod->name));
1061 }
1062 }
1063 ly_print(out, "%s\"%s>\n", uses->name, (close ? "/" : ""));
1064
1065 if (!close) {
1066 level++;
1067 yin_print_nacmext(out, level, node, node->module);
1068 yin_print_snode_common(out, level, node);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001069 for (i = 0; i < uses->iffeature_size; i++) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02001070 yin_print_iffeature(out, level, node->module, &uses->iffeature[i]);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001071 }
1072 if (uses->when) {
1073 yin_print_when(out, level, node->module, uses->when);
1074 }
1075
1076 for (i = 0; i < uses->refine_size; i++) {
1077 yin_print_refine(out, level, node->module, &uses->refine[i]);
1078 }
1079
1080 for (i = 0; i < uses->augment_size; i++) {
1081 yin_print_augment(out, level, node->module, &uses->augment[i]);
1082 }
1083 level--;
1084
Michal Vasko87bb46b2016-02-12 11:51:42 +01001085 yin_print_close(out, level, "uses");
Michal Vaskoa63ca342016-02-05 14:29:19 +01001086 }
1087}
1088
1089static void
1090yin_print_input_output(struct lyout *out, int level, const struct lys_node *node)
1091{
1092 int i;
1093 struct lys_node *sub;
Michal Vasko44fb6382016-06-29 11:12:27 +02001094 struct lys_node_inout *inout = (struct lys_node_inout *)node;
Michal Vaskoa63ca342016-02-05 14:29:19 +01001095
1096 ly_print(out, "%*s<%s>\n", LEVEL, INDENT, (inout->nodetype == LYS_INPUT ? "input" : "output"));
1097
1098 level++;
1099 for (i = 0; i < inout->tpdf_size; i++) {
1100 yin_print_typedef(out, level, node->module, &inout->tpdf[i]);
1101 }
Radek Krejci12032a52016-07-29 15:42:56 +02001102 for (i = 0; i < inout->must_size; i++) {
1103 yin_print_must(out, level, node->module, &inout->must[i]);
1104 }
Michal Vaskoa63ca342016-02-05 14:29:19 +01001105
1106 LY_TREE_FOR(node->child, sub) {
Michal Vasko0c5e9282016-02-15 13:11:57 +01001107 /* augments */
1108 if (sub->parent != node) {
Michal Vaskoa63ca342016-02-05 14:29:19 +01001109 continue;
1110 }
1111 yin_print_snode(out, level, sub,
1112 LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
1113 LYS_USES | LYS_GROUPING | LYS_ANYXML);
1114 }
1115 level--;
1116
Michal Vasko87bb46b2016-02-12 11:51:42 +01001117 yin_print_close(out, level, (inout->nodetype == LYS_INPUT ? "input" : "output"));
Michal Vaskoa63ca342016-02-05 14:29:19 +01001118}
1119
1120static void
Michal Vaskoca7cbc42016-07-01 11:36:53 +02001121yin_print_rpc_action(struct lyout *out, int level, const struct lys_node *node)
Michal Vaskoa63ca342016-02-05 14:29:19 +01001122{
1123 int i, close;
1124 struct lys_node *sub;
Michal Vasko44fb6382016-06-29 11:12:27 +02001125 struct lys_node_rpc_action *rpc = (struct lys_node_rpc_action *)node;
Michal Vaskoa63ca342016-02-05 14:29:19 +01001126
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001127 close = (yin_has_snode_common(node) || rpc->iffeature_size || rpc->tpdf_size || node->child ? 0 : 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001128
Michal Vaskoca7cbc42016-07-01 11:36:53 +02001129 yin_print_open(out, level, (node->nodetype == LYS_RPC ? "rpc" : "action"), "name", node->name, close);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001130
1131 if (!close) {
1132 level++;
1133 yin_print_snode_common(out, level, node);
1134
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001135 for (i = 0; i < rpc->iffeature_size; i++) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02001136 yin_print_iffeature(out, level, node->module, &rpc->iffeature[i]);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001137 }
1138
1139 for (i = 0; i < rpc->tpdf_size; i++) {
1140 yin_print_typedef(out, level, node->module, &rpc->tpdf[i]);
1141 }
1142
1143 LY_TREE_FOR(node->child, sub) {
Michal Vasko0c5e9282016-02-15 13:11:57 +01001144 /* augments */
1145 if (sub->parent != node) {
Michal Vaskoa63ca342016-02-05 14:29:19 +01001146 continue;
1147 }
1148 yin_print_snode(out, level, sub, LYS_GROUPING | LYS_INPUT | LYS_OUTPUT);
1149 }
1150 level--;
1151
Michal Vaskoca7cbc42016-07-01 11:36:53 +02001152 yin_print_close(out, level, (node->nodetype == LYS_RPC ? "rpc" : "action"));
Michal Vaskoa63ca342016-02-05 14:29:19 +01001153 }
1154}
1155
1156static void
1157yin_print_notif(struct lyout *out, int level, const struct lys_node *node)
1158{
1159 int i, close;
1160 struct lys_node *sub;
1161 struct lys_node_notif *notif = (struct lys_node_notif *)node;
1162
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001163 close = (yin_has_snode_common(node) || notif->iffeature_size || notif->tpdf_size || node->child ? 0 : 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001164
Michal Vasko87bb46b2016-02-12 11:51:42 +01001165 yin_print_open(out, level, "notification", "name", node->name, close);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001166
1167 if (!close) {
1168 level++;
1169 yin_print_snode_common(out, level, node);
1170
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001171 for (i = 0; i < notif->iffeature_size; i++) {
Radek Krejci9ff0a922016-07-14 13:08:05 +02001172 yin_print_iffeature(out, level, node->module, &notif->iffeature[i]);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001173 }
1174
1175 for (i = 0; i < notif->tpdf_size; i++) {
1176 yin_print_typedef(out, level, node->module, &notif->tpdf[i]);
1177 }
1178
Radek Krejci12032a52016-07-29 15:42:56 +02001179 for (i = 0; i < notif->must_size; i++) {
1180 yin_print_must(out, level, node->module, &notif->must[i]);
1181 }
1182
Michal Vaskoa63ca342016-02-05 14:29:19 +01001183 LY_TREE_FOR(node->child, sub) {
Michal Vasko0c5e9282016-02-15 13:11:57 +01001184 /* augments */
1185 if (sub->parent != node) {
Michal Vaskoa63ca342016-02-05 14:29:19 +01001186 continue;
1187 }
1188 yin_print_snode(out, level, sub,
1189 LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
1190 LYS_USES | LYS_GROUPING | LYS_ANYXML);
1191 }
1192 level--;
1193
Michal Vasko87bb46b2016-02-12 11:51:42 +01001194 yin_print_close(out, level, "notification");
Michal Vaskoa63ca342016-02-05 14:29:19 +01001195 }
1196}
1197
1198static void
1199yin_print_snode(struct lyout *out, int level, const struct lys_node *node, int mask)
1200{
1201 switch (node->nodetype & mask) {
1202 case LYS_CONTAINER:
1203 yin_print_container(out, level, node);
1204 break;
1205 case LYS_CHOICE:
1206 yin_print_choice(out, level, node);
1207 break;
1208 case LYS_LEAF:
1209 yin_print_leaf(out, level, node);
1210 break;
1211 case LYS_LEAFLIST:
1212 yin_print_leaflist(out, level, node);
1213 break;
1214 case LYS_LIST:
1215 yin_print_list(out, level, node);
1216 break;
1217 case LYS_USES:
1218 yin_print_uses(out, level, node);
1219 break;
1220 case LYS_GROUPING:
1221 yin_print_grouping(out, level, node);
1222 break;
1223 case LYS_ANYXML:
1224 yin_print_anyxml(out, level, node);
1225 break;
1226 case LYS_CASE:
1227 yin_print_case(out, level, node);
1228 break;
Michal Vaskoca7cbc42016-07-01 11:36:53 +02001229 case LYS_ACTION:
1230 yin_print_rpc_action(out, level, node);
1231 break;
Michal Vaskoa63ca342016-02-05 14:29:19 +01001232 case LYS_INPUT:
1233 case LYS_OUTPUT:
1234 yin_print_input_output(out, level, node);
1235 break;
1236 default:
1237 break;
1238 }
1239}
1240
1241static void
1242yin_print_namespaces(struct lyout *out, const struct lys_module *module)
1243{
1244 unsigned int i, lvl;
1245
1246 if (module->type) {
1247 lvl = 11;
1248 } else {
1249 lvl = 8;
1250 }
1251
1252 ly_print(out, "%*sxmlns=\"%s\"", lvl, INDENT, LY_NSYIN);
1253 if (!module->type) {
1254 ly_print(out, "\n%*sxmlns:%s=\"%s\"", lvl, INDENT, module->prefix, module->ns);
1255 }
1256 for (i = 0; i < module->imp_size; ++i) {
Michal Vaskoa63ca342016-02-05 14:29:19 +01001257 ly_print(out, "\n%*sxmlns:%s=\"%s\"", lvl, INDENT, module->imp[i].prefix, module->imp[i].module->ns);
1258 }
1259}
1260
1261int
1262yin_print_model(struct lyout *out, const struct lys_module *module)
1263{
1264 unsigned int i;
1265 int level = 0, close;
1266#define LEVEL (level*2)
1267
1268 struct lys_node *node;
1269
1270 ly_print(out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
1271
Michal Vasko89563fc2016-07-28 16:19:35 +02001272 if (module->deviated == 1) {
Michal Vaskoa63ca342016-02-05 14:29:19 +01001273 ly_print(out, "<!-- DEVIATED -->\n");
1274 }
1275
1276 /* (sub)module-header-stmts */
1277 if (module->type) {
1278 ly_print(out, "<submodule name=\"%s\"\n", module->name);
1279 yin_print_namespaces(out, module);
1280 ly_print(out, ">\n");
1281
1282 level++;
1283 if (module->version) {
Michal Vasko87bb46b2016-02-12 11:51:42 +01001284 yin_print_open(out, level, "yang-version", "value",
1285 ((struct lys_submodule *)module)->belongsto->version == 2 ? "1.1" : "1", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001286 }
Michal Vasko87bb46b2016-02-12 11:51:42 +01001287 yin_print_open(out, level, "belongs-to", "module", ((struct lys_submodule *)module)->belongsto->name, 0);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001288
1289 level++;
Michal Vasko87bb46b2016-02-12 11:51:42 +01001290 yin_print_open(out, level, "prefix", "value", module->prefix, 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001291 level--;
1292
Michal Vasko87bb46b2016-02-12 11:51:42 +01001293 yin_print_close(out, level, "belongs-to");
Michal Vaskoa63ca342016-02-05 14:29:19 +01001294 } else {
1295 ly_print(out, "<module name=\"%s\"\n", module->name);
1296 yin_print_namespaces(out, module);
1297 ly_print(out, ">\n");
1298
1299 level++;
1300 if (module->version) {
Michal Vasko87bb46b2016-02-12 11:51:42 +01001301 yin_print_open(out, level, "yang-version", "value", module->version == 2 ? "1.1" : "1", 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001302 }
Michal Vasko87bb46b2016-02-12 11:51:42 +01001303 yin_print_open(out, level, "namespace", "uri", module->ns, 1);
1304 yin_print_open(out, level, "prefix", "value", module->prefix, 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001305 }
1306
1307 /* linkage-stmts */
1308 for (i = 0; i < module->imp_size; i++) {
Michal Vasko87bb46b2016-02-12 11:51:42 +01001309 yin_print_open(out, level, "import", "module", module->imp[i].module->name, 0);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001310
1311 level++;
Michal Vasko87bb46b2016-02-12 11:51:42 +01001312 yin_print_open(out, level, "prefix", "value", module->imp[i].prefix, 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001313 if (module->imp[i].rev[0]) {
Michal Vasko87bb46b2016-02-12 11:51:42 +01001314 yin_print_open(out, level, "revision-date", "date", module->imp[i].rev, 1);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001315 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02001316 if (module->imp[i].dsc) {
1317 yin_print_text(out, level, "description", module->imp[i].dsc);
1318 }
1319 if (module->imp[i].ref) {
1320 yin_print_text(out, level, "reference", module->imp[i].ref);
1321 }
Michal Vaskoa63ca342016-02-05 14:29:19 +01001322 level--;
1323
Michal Vasko87bb46b2016-02-12 11:51:42 +01001324 yin_print_close(out, level, "import");
Michal Vaskoa63ca342016-02-05 14:29:19 +01001325 }
1326 for (i = 0; i < module->inc_size; i++) {
1327 if (module->inc[i].external) {
1328 continue;
1329 }
1330
1331 close = (module->inc[i].rev[0] ? 0 : 1);
Radek Krejci268dc5f2016-03-04 10:35:16 +01001332 yin_print_open(out, level, "include", "module", module->inc[i].submodule->name, close);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001333
1334 if (!close) {
1335 level++;
Michal Vasko87bb46b2016-02-12 11:51:42 +01001336 yin_print_open(out, level, "revision-date", "date", module->inc[i].rev, 1);
Michal Vasko8bfe3812016-07-27 13:37:52 +02001337 if (module->inc[i].dsc) {
1338 yin_print_text(out, level, "description", module->inc[i].dsc);
1339 }
1340 if (module->inc[i].ref) {
1341 yin_print_text(out, level, "reference", module->inc[i].ref);
1342 }
Michal Vaskoa63ca342016-02-05 14:29:19 +01001343 level--;
1344
Michal Vasko87bb46b2016-02-12 11:51:42 +01001345 yin_print_close(out, level, "include");
Michal Vaskoa63ca342016-02-05 14:29:19 +01001346 }
1347 }
1348
1349 /* meta-stmts */
1350 if (module->org) {
1351 yin_print_text(out, level, "organization", module->org);
1352 }
1353 if (module->contact) {
1354 yin_print_text(out, level, "contact", module->contact);
1355 }
1356 if (module->dsc) {
1357 yin_print_text(out, level, "description", module->dsc);
1358 }
1359 if (module->ref) {
1360 yin_print_text(out, level, "reference", module->ref);
1361 }
1362
1363 /* revision-stmts */
1364 for (i = 0; i < module->rev_size; i++) {
1365 close = (module->rev[i].dsc || module->rev[i].ref ? 0 : 1);
Michal Vasko87bb46b2016-02-12 11:51:42 +01001366 yin_print_open(out, level, "revision", "date", module->rev[i].date, close);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001367
1368 if (!close) {
1369 level++;
1370 if (module->rev[i].dsc) {
1371 yin_print_text(out, level, "description", module->rev[i].dsc);
1372 }
1373 if (module->rev[i].ref) {
1374 yin_print_text(out, level, "reference", module->rev[i].ref);
1375 }
1376 level--;
1377
Michal Vasko87bb46b2016-02-12 11:51:42 +01001378 yin_print_close(out, level, "revision");
Michal Vaskoa63ca342016-02-05 14:29:19 +01001379 }
1380 }
1381
1382 /* body-stmts */
1383 for (i = 0; i < module->features_size; i++) {
1384 yin_print_feature(out, level, &module->features[i]);
1385 }
1386
1387 for (i = 0; i < module->ident_size; i++) {
1388 yin_print_identity(out, level, &module->ident[i]);
1389 }
1390
1391 for (i = 0; i < module->tpdf_size; i++) {
1392 yin_print_typedef(out, level, module, &module->tpdf[i]);
1393 }
1394
1395 for (i = 0; i < module->deviation_size; ++i) {
1396 yin_print_deviation(out, level, module, &module->deviation[i]);
1397 }
1398
Radek Krejcic4283442016-04-22 09:19:27 +02001399 LY_TREE_FOR(lys_main_module(module)->data, node) {
Michal Vaskoa63ca342016-02-05 14:29:19 +01001400 if (node->module != module) {
Michal Vasko0c5e9282016-02-15 13:11:57 +01001401 /* data from submodules */
Michal Vaskoa63ca342016-02-05 14:29:19 +01001402 continue;
1403 }
1404
1405 switch (node->nodetype) {
1406 case LYS_RPC:
Michal Vaskoca7cbc42016-07-01 11:36:53 +02001407 yin_print_rpc_action(out, level, node);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001408 break;
1409 case LYS_NOTIF:
1410 yin_print_notif(out, level, node);
1411 break;
1412 default:
1413 yin_print_snode(out, level, node,
1414 LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
1415 LYS_USES | LYS_GROUPING | LYS_ANYXML);
1416 break;
1417 }
1418 }
1419
1420 for (i = 0; i < module->augment_size; i++) {
1421 yin_print_augment(out, level, module, &module->augment[i]);
1422 }
1423
1424 if (module->type) {
1425 ly_print(out, "</submodule>\n");
1426 } else {
1427 ly_print(out, "</module>\n");
1428 }
Michal Vasko95068c42016-03-24 14:58:11 +01001429 ly_print_flush(out);
Michal Vaskoa63ca342016-02-05 14:29:19 +01001430
1431 return EXIT_SUCCESS;
1432#undef LEVEL
1433}
1434