1 /**
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 *
8 * 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
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14 #define _GNU_SOURCE
15 #include <stdlib.h>
16 #include <string.h>
17 #include <assert.h>
18
19 #include "common.h"
20 #include "context.h"
21 #include "printer.h"
22 #include "tree_schema.h"
23 #include "xml_internal.h"
24
25 #define INDENT ""
26 #define LEVEL (level*2)
27
28 static void yin_print_snode(struct lyout *out, int level, const struct lys_node *node, int mask);
29 static void yin_print_extension_instances(struct lyout *out, int level, const struct lys_module *module,
30 LYEXT_SUBSTMT substmt, uint8_t substmt_index,
31 struct lys_ext_instance **ext, unsigned int count);
32
33 /* endflag :
34 * -1: /> - empty element
35 * 0: - no end
36 * 1: > - element with children
37 */
38 static void
yin_print_open(struct lyout * out,int level,const char * elem_prefix,const char * elem_name,const char * attr_name,const char * attr_value,int endflag)39 yin_print_open(struct lyout *out, int level, const char *elem_prefix, const char *elem_name,
40 const char *attr_name, const char *attr_value, int endflag)
41 {
42 if (elem_prefix) {
43 ly_print(out, "%*s<%s:%s", LEVEL, INDENT, elem_prefix, elem_name);
44 } else {
45 ly_print(out, "%*s<%s", LEVEL, INDENT, elem_name);
46 }
47
48 if (attr_name) {
49 ly_print(out, " %s=\"", attr_name);
50 lyxml_dump_text(out, attr_value, LYXML_DATA_ATTR);
51 ly_print(out, "\"%s", endflag == -1 ? "/>\n" : endflag == 1 ? ">\n" : "");
52 } else if (endflag) {
53 ly_print(out, endflag == -1 ? "/>\n" : ">\n");
54 }
55 }
56
57 /*
58 * endflag:
59 * 0: /> - closing empty element
60 * 1: </elem_name> - closing element with children
61 */
62 static void
yin_print_close(struct lyout * out,int level,const char * elem_prefix,const char * elem_name,int endflag)63 yin_print_close(struct lyout *out, int level, const char *elem_prefix, const char *elem_name, int endflag)
64 {
65 if (endflag) {
66 if (elem_prefix) {
67 ly_print(out, "%*s</%s:%s>\n", LEVEL, INDENT, elem_prefix, elem_name);
68 } else {
69 ly_print(out, "%*s</%s>\n", LEVEL, INDENT, elem_name);
70 }
71 } else {
72 ly_print(out, "/>\n");
73 }
74 }
75
76 /*
77 * par_close_flag
78 * 0 - parent not yet closed, printing >\n, setting flag to 1
79 * 1 or NULL - parent already closed, do nothing
80 */
81 static void
yin_print_close_parent(struct lyout * out,int * par_close_flag)82 yin_print_close_parent(struct lyout *out, int *par_close_flag)
83 {
84 if (par_close_flag && !(*par_close_flag)) {
85 (*par_close_flag) = 1;
86 ly_print(out, ">\n");
87 }
88 }
89
90 static void
yin_print_arg(struct lyout * out,int level,const char * arg,const char * text)91 yin_print_arg(struct lyout *out, int level, const char *arg, const char *text)
92 {
93 ly_print(out, "%*s<%s>", LEVEL, INDENT, arg);
94 lyxml_dump_text(out, text, LYXML_DATA_ELEM);
95 ly_print(out, "</%s>\n", arg);
96 }
97
98 static void
yin_print_substmt(struct lyout * out,int level,LYEXT_SUBSTMT substmt,uint8_t substmt_index,const char * text,const struct lys_module * module,struct lys_ext_instance ** ext,unsigned int ext_size)99 yin_print_substmt(struct lyout *out, int level, LYEXT_SUBSTMT substmt, uint8_t substmt_index, const char *text,
100 const struct lys_module *module, struct lys_ext_instance **ext, unsigned int ext_size)
101 {
102 int i, content = 0;
103
104 if (!text) {
105 /* nothing to print */
106 return;
107 }
108
109 if (ext_substmt_info[substmt].flags & SUBST_FLAG_YIN) {
110 content = 1;
111 yin_print_open(out, level, NULL, ext_substmt_info[substmt].name,
112 NULL, NULL, content);
113 } else {
114 yin_print_open(out, level, NULL, ext_substmt_info[substmt].name,
115 ext_substmt_info[substmt].arg, text, content);
116 }
117 /* extensions */
118 i = -1;
119 do {
120 i = lys_ext_iter(ext, ext_size, i + 1, substmt);
121 } while (i != -1 && ext[i]->insubstmt_index != substmt_index);
122 if (i != -1) {
123 yin_print_close_parent(out, &content);
124 do {
125 yin_print_extension_instances(out, level + 1, module, substmt, substmt_index, &ext[i], 1);
126 do {
127 i = lys_ext_iter(ext, ext_size, i + 1, substmt);
128 } while (i != -1 && ext[i]->insubstmt_index != substmt_index);
129 } while (i != -1);
130 }
131
132 /* argument as yin-element */
133 if (ext_substmt_info[substmt].flags & SUBST_FLAG_YIN) {
134 yin_print_arg(out, level + 1, ext_substmt_info[substmt].arg, text);
135 }
136
137 yin_print_close(out, level, NULL, ext_substmt_info[substmt].name, content);
138 }
139
140 static void
yin_print_iffeature(struct lyout * out,int level,const struct lys_module * module,struct lys_iffeature * iffeature)141 yin_print_iffeature(struct lyout *out, int level, const struct lys_module *module, struct lys_iffeature *iffeature)
142 {
143 ly_print(out, "%*s<if-feature name=\"", LEVEL, INDENT);
144 ly_print_iffeature(out, module, iffeature, 0);
145
146 /* extensions */
147 if (iffeature->ext_size) {
148 ly_print(out, "\">\n");
149 yin_print_extension_instances(out, level + 1, module, LYEXT_SUBSTMT_SELF, 0, iffeature->ext, iffeature->ext_size);
150 ly_print(out, "%*s</if-feature>\n", LEVEL, INDENT);
151 } else {
152 ly_print(out, "\"/>\n");
153 }
154 }
155
156 /*
157 * Covers:
158 * extension (instances), if-features, config, mandatory, status, description, reference
159 */
160 #define SNODE_COMMON_EXT 0x01
161 #define SNODE_COMMON_IFF 0x02
162 #define SNODE_COMMON_CONFIG 0x04
163 #define SNODE_COMMON_MAND 0x08
164 #define SNODE_COMMON_STATUS 0x10
165 #define SNODE_COMMON_DSC 0x20
166 #define SNODE_COMMON_REF 0x40
167 static void
yin_print_snode_common(struct lyout * out,int level,const struct lys_node * node,const struct lys_module * module,int * par_close_flag,int mask)168 yin_print_snode_common(struct lyout *out, int level, const struct lys_node *node, const struct lys_module *module,
169 int *par_close_flag, int mask)
170 {
171 int i;
172 const char *status = NULL;
173
174 /* extensions */
175 if ((mask & SNODE_COMMON_EXT) && node->ext_size) {
176 yin_print_close_parent(out, par_close_flag);
177 yin_print_extension_instances(out, level, module, LYEXT_SUBSTMT_SELF, 0, node->ext, node->ext_size);
178 }
179
180 /* if-features */
181 if (mask & SNODE_COMMON_IFF) {
182 for (i = 0; i < node->iffeature_size; ++i) {
183 yin_print_close_parent(out, par_close_flag);
184 yin_print_iffeature(out, level, module, &node->iffeature[i]);
185 }
186 }
187
188 /* config */
189 if (mask & SNODE_COMMON_CONFIG) {
190 /* get info if there is an extension for the config statement */
191 i = lys_ext_iter(node->ext, node->ext_size, 0, LYEXT_SUBSTMT_CONFIG);
192
193 if (lys_parent(node)) {
194 if ((node->flags & LYS_CONFIG_SET) || i != -1) {
195 /* print config when it differs from the parent or if it has an extension instance ... */
196 if (node->flags & LYS_CONFIG_W) {
197 yin_print_close_parent(out, par_close_flag);
198 yin_print_substmt(out, level, LYEXT_SUBSTMT_CONFIG, 0, "true",
199 module, node->ext, node->ext_size);
200 } else if (node->flags & LYS_CONFIG_R) {
201 yin_print_close_parent(out, par_close_flag);
202 yin_print_substmt(out, level, LYEXT_SUBSTMT_CONFIG, 0, "false",
203 module, node->ext, node->ext_size);
204 }
205 }
206 } else if (node->flags & LYS_CONFIG_R) {
207 /* ... or it's a top-level state node */
208 yin_print_close_parent(out, par_close_flag);
209 yin_print_substmt(out, level, LYEXT_SUBSTMT_CONFIG, 0, "false",
210 module, node->ext, node->ext_size);
211 } else if (i != -1) {
212 /* the config has an extension, so we have to print it */
213 yin_print_close_parent(out, par_close_flag);
214 yin_print_substmt(out, level, LYEXT_SUBSTMT_CONFIG, 0, "true",
215 module, node->ext, node->ext_size);
216 }
217 }
218
219 /* mandatory */
220 if ((mask & SNODE_COMMON_MAND) && (node->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
221 if (node->flags & LYS_MAND_TRUE) {
222 yin_print_close_parent(out, par_close_flag);
223 yin_print_substmt(out, level, LYEXT_SUBSTMT_MANDATORY, 0, "true",
224 module, node->ext, node->ext_size);
225 } else if (node->flags & LYS_MAND_FALSE) {
226 yin_print_close_parent(out, par_close_flag);
227 yin_print_substmt(out, level, LYEXT_SUBSTMT_MANDATORY, 0, "false",
228 module, node->ext, node->ext_size);
229 }
230 }
231
232 /* status */
233 if (mask & SNODE_COMMON_STATUS) {
234 if (node->flags & LYS_STATUS_CURR) {
235 yin_print_close_parent(out, par_close_flag);
236 status = "current";
237 } else if (node->flags & LYS_STATUS_DEPRC) {
238 yin_print_close_parent(out, par_close_flag);
239 status = "deprecated";
240 } else if (node->flags & LYS_STATUS_OBSLT) {
241 yin_print_close_parent(out, par_close_flag);
242 status = "obsolete";
243 }
244 yin_print_substmt(out, level, LYEXT_SUBSTMT_STATUS, 0, status, module, node->ext, node->ext_size);
245 }
246
247 /* description */
248 if ((mask & SNODE_COMMON_DSC) && node->dsc) {
249 yin_print_close_parent(out, par_close_flag);
250 yin_print_substmt(out, level, LYEXT_SUBSTMT_DESCRIPTION, 0, node->dsc,
251 module, node->ext, node->ext_size);
252 }
253
254 /* reference */
255 if ((mask & SNODE_COMMON_REF) && node->ref) {
256 yin_print_close_parent(out, par_close_flag);
257 yin_print_substmt(out, level, LYEXT_SUBSTMT_REFERENCE, 0, node->ref,
258 module, node->ext, node->ext_size);
259 }
260 }
261
262 static void
yin_print_extension(struct lyout * out,int level,const struct lys_ext * ext)263 yin_print_extension(struct lyout *out, int level, const struct lys_ext *ext)
264 {
265 int close = 0, close2 = 0, i;
266
267 yin_print_open(out, level, NULL, "extension", "name", ext->name, close);
268 level++;
269
270 yin_print_snode_common(out, level, (struct lys_node *)ext, ext->module, &close,
271 SNODE_COMMON_EXT);
272
273 if (ext->argument) {
274 yin_print_close_parent(out, &close);
275 yin_print_open(out, level, NULL, "argument", "name", ext->argument, close2);
276 i = -1;
277 while ((i = lys_ext_iter(ext->ext, ext->ext_size, i + 1, LYEXT_SUBSTMT_ARGUMENT)) != -1) {
278 yin_print_close_parent(out, &close2);
279 yin_print_extension_instances(out, level + 1, ext->module, LYEXT_SUBSTMT_ARGUMENT, 0, &ext->ext[i], 1);
280 }
281 if ((ext->flags & LYS_YINELEM) || lys_ext_iter(ext->ext, ext->ext_size, 0, LYEXT_SUBSTMT_YINELEM) != -1) {
282 yin_print_close_parent(out, &close2);
283 yin_print_substmt(out, level + 1, LYEXT_SUBSTMT_YINELEM, 0,
284 (ext->flags & LYS_YINELEM) ? "true" : "false", ext->module, ext->ext, ext->ext_size);
285 }
286 yin_print_close(out, level, NULL, "argument", close2);
287 }
288
289 yin_print_snode_common(out, level, (struct lys_node *)ext, ext->module, &close,
290 SNODE_COMMON_STATUS | SNODE_COMMON_DSC | SNODE_COMMON_REF);
291
292 level--;
293 yin_print_close(out, level, NULL, "extension", close);
294 }
295
296 static void
yin_print_restr(struct lyout * out,int level,const struct lys_module * module,const struct lys_restr * restr,int * flag)297 yin_print_restr(struct lyout *out, int level, const struct lys_module *module, const struct lys_restr *restr,
298 int *flag)
299 {
300 if (restr->ext_size) {
301 yin_print_close_parent(out, flag);
302 yin_print_extension_instances(out, level, module, LYEXT_SUBSTMT_SELF, 0,
303 restr->ext, restr->ext_size);
304 }
305 if (restr->expr[0] == 0x15) {
306 /* special byte value in pattern's expression: 0x15 - invert-match, 0x06 - match */
307 yin_print_close_parent(out, flag);
308 yin_print_substmt(out, level, LYEXT_SUBSTMT_MODIFIER, 0, "invert-match", module,
309 restr->ext, restr->ext_size);
310 }
311 if (restr->emsg != NULL) {
312 yin_print_close_parent(out, flag);
313 yin_print_substmt(out, level, LYEXT_SUBSTMT_ERRMSG, 0, restr->emsg,
314 module, restr->ext, restr->ext_size);
315 }
316 if (restr->eapptag != NULL) {
317 yin_print_close_parent(out, flag);
318 yin_print_substmt(out, level, LYEXT_SUBSTMT_ERRTAG, 0, restr->eapptag,
319 module, restr->ext, restr->ext_size);
320 }
321 if (restr->dsc != NULL) {
322 yin_print_close_parent(out, flag);
323 yin_print_substmt(out, level, LYEXT_SUBSTMT_DESCRIPTION, 0, restr->dsc,
324 module, restr->ext, restr->ext_size);
325 }
326 if (restr->ref != NULL) {
327 yin_print_close_parent(out, flag);
328 yin_print_substmt(out, level, LYEXT_SUBSTMT_REFERENCE, 0, restr->ref,
329 module, restr->ext, restr->ext_size);
330 }
331 }
332
333 /* covers length, range, pattern*/
334 static void
yin_print_typerestr(struct lyout * out,int level,const struct lys_module * module,const struct lys_restr * restr,const char * elem_name)335 yin_print_typerestr(struct lyout *out, int level, const struct lys_module *module,
336 const struct lys_restr *restr, const char *elem_name)
337 {
338 int content = 0;
339 int pattern = 0;
340
341 if (restr->expr[0] == 0x06 || restr->expr[0] == 0x15) {
342 pattern = 1;
343 }
344
345 yin_print_open(out, level, NULL, elem_name, "value", pattern ? &restr->expr[1] : restr->expr , content);
346 yin_print_restr(out, level + 1, module, restr, &content);
347 yin_print_close(out, level, NULL, elem_name, content);
348 }
349
350 static void
yin_print_feature(struct lyout * out,int level,const struct lys_feature * feat)351 yin_print_feature(struct lyout *out, int level, const struct lys_feature *feat)
352 {
353 int close = 0;
354
355 yin_print_open(out, level, NULL, "feature", "name", feat->name, close);
356 yin_print_snode_common(out, level + 1, (struct lys_node *)feat, feat->module, &close, SNODE_COMMON_EXT |
357 SNODE_COMMON_IFF | SNODE_COMMON_STATUS | SNODE_COMMON_DSC | SNODE_COMMON_REF);
358 yin_print_close(out, level, NULL, "feature", close);
359 }
360
361 static void
yin_print_when(struct lyout * out,int level,const struct lys_module * module,const struct lys_when * when)362 yin_print_when(struct lyout *out, int level, const struct lys_module *module, const struct lys_when *when)
363 {
364 int flag = 0;
365 const char *str;
366
367 str = transform_json2schema(module, when->cond);
368 if (!str) {
369 ly_print(out, "(!error!)");
370 return;
371 }
372
373 ly_print(out, "%*s<when condition=\"", LEVEL, INDENT);
374 lyxml_dump_text(out, str, LYXML_DATA_ATTR);
375 ly_print(out, "\"");
376 lydict_remove(module->ctx, str);
377
378 level++;
379
380 if (when->ext_size) {
381 /* extension is stored in lys_when incompatible with lys_node, so we cannot use yang_print_snode_common() */
382 yin_print_close_parent(out, &flag);
383 yin_print_extension_instances(out, level, module, LYEXT_SUBSTMT_SELF, 0, when->ext, when->ext_size);
384 }
385 if (when->dsc != NULL) {
386 yin_print_close_parent(out, &flag);
387 yin_print_substmt(out, level, LYEXT_SUBSTMT_DESCRIPTION, 0, when->dsc,
388 module, when->ext, when->ext_size);
389 }
390 if (when->ref != NULL) {
391 yin_print_close_parent(out, &flag);
392 yin_print_substmt(out, level, LYEXT_SUBSTMT_REFERENCE, 0, when->ref,
393 module, when->ext, when->ext_size);
394 }
395
396 level--;
397 yin_print_close(out, level, NULL, "when", flag);
398 }
399
400 static void
yin_print_unsigned(struct lyout * out,int level,LYEXT_SUBSTMT substmt,uint8_t substmt_index,const struct lys_module * module,struct lys_ext_instance ** ext,unsigned int ext_size,unsigned int attr_value)401 yin_print_unsigned(struct lyout *out, int level, LYEXT_SUBSTMT substmt, uint8_t substmt_index,
402 const struct lys_module *module, struct lys_ext_instance **ext, unsigned int ext_size,
403 unsigned int attr_value)
404 {
405 char *str;
406
407 if (asprintf(&str, "%u", attr_value) == -1) {
408 LOGMEM(module->ctx);
409 } else {
410 yin_print_substmt(out, level, substmt, substmt_index, str, module, ext, ext_size);
411 free(str);
412 }
413 }
414
415 static void
yin_print_signed(struct lyout * out,int level,LYEXT_SUBSTMT substmt,uint8_t substmt_index,const struct lys_module * module,struct lys_ext_instance ** ext,unsigned int ext_size,signed int attr_value)416 yin_print_signed(struct lyout *out, int level, LYEXT_SUBSTMT substmt, uint8_t substmt_index,
417 const struct lys_module *module, struct lys_ext_instance **ext, unsigned int ext_size,
418 signed int attr_value)
419 {
420 char *str;
421
422 if (asprintf(&str, "%d", attr_value) == -1) {
423 LOGMEM(module->ctx);
424 } else {
425 yin_print_substmt(out, level, substmt, substmt_index, str, module, ext, ext_size);
426 free(str);
427 }
428 }
429
430 static void
yin_print_type(struct lyout * out,int level,const struct lys_module * module,const struct lys_type * type)431 yin_print_type(struct lyout *out, int level, const struct lys_module *module, const struct lys_type *type)
432 {
433 unsigned int i;
434 int content = 0, content2 = 0;
435 const char *str;
436 char *s;
437 struct lys_module *mod;
438
439 if (!lys_type_is_local(type)) {
440 ly_print(out, "%*s<type name=\"%s:%s\"", LEVEL, INDENT,
441 transform_module_name2import_prefix(module, lys_main_module(type->der->module)->name), type->der->name);
442 } else {
443 yin_print_open(out, level, NULL, "type", "name", type->der->name, content);
444 }
445 level++;
446
447 /* extensions */
448 if (type->ext_size) {
449 yin_print_close_parent(out, &content);
450 yin_print_extension_instances(out, level, module, LYEXT_SUBSTMT_SELF, 0, type->ext, type->ext_size);
451 }
452
453
454 switch (type->base) {
455 case LY_TYPE_BINARY:
456 if (type->info.binary.length) {
457 yin_print_close_parent(out, &content);
458 yin_print_typerestr(out, level, module, type->info.binary.length, "length");
459 }
460 break;
461 case LY_TYPE_BITS:
462 for (i = 0; i < type->info.bits.count; ++i) {
463 content2 = 0;
464 yin_print_close_parent(out, &content);
465 yin_print_open(out, level, NULL, "bit", "name", type->info.bits.bit[i].name, content2);
466 yin_print_snode_common(out, level + 1, (struct lys_node *)&type->info.bits.bit[i], module, &content2,
467 SNODE_COMMON_EXT | SNODE_COMMON_IFF);
468 if (!(type->info.bits.bit[i].flags & LYS_AUTOASSIGNED)) {
469 yin_print_close_parent(out, &content2);
470 yin_print_unsigned(out, level + 1, LYEXT_SUBSTMT_POSITION, 0, module,
471 type->info.bits.bit[i].ext, type->info.bits.bit[i].ext_size,
472 type->info.bits.bit[i].pos);
473 }
474 yin_print_snode_common(out, level + 1, (struct lys_node *)&type->info.bits.bit[i], module, &content2,
475 SNODE_COMMON_STATUS | SNODE_COMMON_DSC | SNODE_COMMON_REF);
476 yin_print_close(out, level, NULL, "bit", content2);
477 }
478 break;
479 case LY_TYPE_DEC64:
480 if (!type->der->type.der) {
481 yin_print_close_parent(out, &content);
482 yin_print_unsigned(out, level, LYEXT_SUBSTMT_DIGITS, 0, module,
483 type->ext, type->ext_size, type->info.dec64.dig);
484 }
485 if (type->info.dec64.range) {
486 yin_print_close_parent(out, &content);
487 yin_print_typerestr(out, level, module, type->info.dec64.range, "range");
488 }
489 break;
490 case LY_TYPE_ENUM:
491 for (i = 0; i < type->info.enums.count; i++) {
492 content2 = 0;
493 yin_print_close_parent(out, &content);
494 yin_print_open(out, level, NULL, "enum", "name", type->info.enums.enm[i].name, content2);
495 yin_print_snode_common(out, level + 1, (struct lys_node *)&type->info.enums.enm[i], module, &content2,
496 SNODE_COMMON_EXT | SNODE_COMMON_IFF);
497 if (!(type->info.enums.enm[i].flags & LYS_AUTOASSIGNED)) {
498 yin_print_close_parent(out, &content2);
499 yin_print_signed(out, level + 1, LYEXT_SUBSTMT_VALUE, 0, module,
500 type->info.enums.enm[i].ext, type->info.enums.enm[i].ext_size,
501 type->info.enums.enm[i].value);
502 }
503 yin_print_snode_common(out, level + 1, (struct lys_node *)&type->info.enums.enm[i], module, &content2,
504 SNODE_COMMON_STATUS | SNODE_COMMON_DSC | SNODE_COMMON_REF);
505 yin_print_close(out, level, NULL, "enum", content2);
506 }
507 break;
508 case LY_TYPE_IDENT:
509 if (type->info.ident.count) {
510 yin_print_close_parent(out, &content);
511 for (i = 0; i < type->info.ident.count; ++i) {
512 mod = lys_main_module(type->info.ident.ref[i]->module);
513 if (lys_main_module(module) == mod) {
514 yin_print_substmt(out, level, LYEXT_SUBSTMT_BASE, 0, type->info.ident.ref[i]->name,
515 module, type->info.ident.ref[i]->ext, type->info.ident.ref[i]->ext_size);
516 } else {
517 if (asprintf(&s, "%s:%s", transform_module_name2import_prefix(module, mod->name),
518 type->info.ident.ref[i]->name) == -1) {
519 LOGMEM(module->ctx);
520 } else {
521 yin_print_substmt(out, level, LYEXT_SUBSTMT_BASE, 0, s,
522 module, type->info.ident.ref[i]->ext, type->info.ident.ref[i]->ext_size);
523 free(s);
524 }
525 }
526 }
527 }
528 break;
529 case LY_TYPE_INST:
530 if (type->info.inst.req == 1) {
531 yin_print_close_parent(out, &content);
532 yin_print_substmt(out, level, LYEXT_SUBSTMT_REQINSTANCE, 0, "true", module, type->ext, type->ext_size);
533 } else if (type->info.inst.req == -1) {
534 yin_print_close_parent(out, &content);
535 yin_print_substmt(out, level, LYEXT_SUBSTMT_REQINSTANCE, 0, "false", module, type->ext, type->ext_size);
536 }
537 break;
538 case LY_TYPE_INT8:
539 case LY_TYPE_INT16:
540 case LY_TYPE_INT32:
541 case LY_TYPE_INT64:
542 case LY_TYPE_UINT8:
543 case LY_TYPE_UINT16:
544 case LY_TYPE_UINT32:
545 case LY_TYPE_UINT64:
546 if (type->info.num.range) {
547 yin_print_close_parent(out, &content);
548 yin_print_typerestr(out, level, module, type->info.num.range, "range");
549 }
550 break;
551 case LY_TYPE_LEAFREF:
552 if (ly_strequal(type->der->name, "leafref", 0)) {
553 yin_print_close_parent(out, &content);
554 str = transform_json2schema(module, type->info.lref.path);
555 yin_print_substmt(out, level, LYEXT_SUBSTMT_PATH, 0, str, module, type->ext, type->ext_size);
556 lydict_remove(module->ctx, str);
557 }
558 if (type->info.lref.req == 1) {
559 yin_print_close_parent(out, &content);
560 yin_print_substmt(out, level, LYEXT_SUBSTMT_REQINSTANCE, 0, "true", module, type->ext, type->ext_size);
561 } else if (type->info.lref.req == -1) {
562 yin_print_close_parent(out, &content);
563 yin_print_substmt(out, level, LYEXT_SUBSTMT_REQINSTANCE, 0, "false", module, type->ext, type->ext_size);
564 }
565 break;
566 case LY_TYPE_STRING:
567 if (type->info.str.length) {
568 yin_print_close_parent(out, &content);
569 yin_print_typerestr(out, level, module, type->info.str.length, "length");
570 }
571 for (i = 0; i < type->info.str.pat_count; i++) {
572 yin_print_close_parent(out, &content);
573 yin_print_typerestr(out, level, module, &type->info.str.patterns[i], "pattern");
574 }
575 break;
576 case LY_TYPE_UNION:
577 for (i = 0; i < type->info.uni.count; ++i) {
578 yin_print_close_parent(out, &content);
579 yin_print_type(out, level, module, &type->info.uni.types[i]);
580 }
581 break;
582 default:
583 /* other types do not have substatements */
584 break;
585 }
586
587 level--;
588 yin_print_close(out, level, NULL, "type", content);
589 }
590
591 static void
yin_print_must(struct lyout * out,int level,const struct lys_module * module,const struct lys_restr * must)592 yin_print_must(struct lyout *out, int level, const struct lys_module *module, const struct lys_restr *must)
593 {
594 const char *str;
595 int content = 0;
596
597 str = transform_json2schema(module, must->expr);
598 if (!str) {
599 ly_print(out, "(!error!)");
600 return;
601 }
602
603 ly_print(out, "%*s<must condition=\"", LEVEL, INDENT);
604 lyxml_dump_text(out, str, LYXML_DATA_ATTR);
605 ly_print(out, "\"");
606 lydict_remove(module->ctx, str);
607
608 yin_print_restr(out, level + 1, module, must, &content);
609 yin_print_close(out, level, NULL, "must", content);
610 }
611
612 static void
yin_print_unique(struct lyout * out,int level,const struct lys_module * module,const struct lys_unique * uniq)613 yin_print_unique(struct lyout *out, int level, const struct lys_module *module, const struct lys_unique *uniq)
614 {
615 int i;
616 const char *str;
617
618 ly_print(out, "%*s<unique tag=\"", LEVEL, INDENT);
619 for (i = 0; i < uniq->expr_size; i++) {
620 str = transform_json2schema(module, uniq->expr[i]);
621 ly_print(out, "%s%s", str, i + 1 < uniq->expr_size ? " " : "");
622 lydict_remove(module->ctx, str);
623 }
624 ly_print(out, "\"");
625 }
626
627 static void
yin_print_refine(struct lyout * out,int level,const struct lys_module * module,const struct lys_refine * refine)628 yin_print_refine(struct lyout *out, int level, const struct lys_module *module, const struct lys_refine *refine)
629 {
630 int i, content = 0;
631 const char *str;
632
633 str = transform_json2xml(module, refine->target_name, 0, NULL, NULL, NULL);
634 yin_print_open(out, level, NULL, "refine", "target-node", str, content);
635 lydict_remove(module->ctx, str);
636
637 level++;
638 yin_print_snode_common(out, level, (struct lys_node *)refine, module, &content,
639 SNODE_COMMON_EXT | SNODE_COMMON_IFF);
640 for (i = 0; i < refine->must_size; ++i) {
641 yin_print_close_parent(out, &content);
642 yin_print_must(out, level, module, &refine->must[i]);
643 }
644 if (refine->target_type == LYS_CONTAINER && refine->mod.presence) {
645 yin_print_close_parent(out, &content);
646 yin_print_substmt(out, level, LYEXT_SUBSTMT_PRESENCE, 0, refine->mod.presence,
647 module, refine->ext, refine->ext_size);
648 }
649 for (i = 0; i < refine->dflt_size; ++i) {
650 yin_print_close_parent(out, &content);
651 yin_print_substmt(out, level, LYEXT_SUBSTMT_DEFAULT, i, refine->dflt[i],
652 module, refine->ext, refine->ext_size);
653 }
654 if (refine->flags & LYS_CONFIG_W) {
655 yin_print_close_parent(out, &content);
656 yin_print_substmt(out, level, LYEXT_SUBSTMT_CONFIG, 0, "true", module, refine->ext, refine->ext_size);
657 } else if (refine->flags & LYS_CONFIG_R) {
658 yin_print_close_parent(out, &content);
659 yin_print_substmt(out, level, LYEXT_SUBSTMT_CONFIG, 0, "false", module, refine->ext, refine->ext_size);
660 }
661 if (refine->flags & LYS_MAND_TRUE) {
662 yin_print_close_parent(out, &content);
663 yin_print_substmt(out, level, LYEXT_SUBSTMT_MANDATORY, 0, "true", module, refine->ext, refine->ext_size);
664 } else if (refine->flags & LYS_MAND_FALSE) {
665 yin_print_close_parent(out, &content);
666 yin_print_substmt(out, level, LYEXT_SUBSTMT_MANDATORY, 0, "false", module, refine->ext, refine->ext_size);
667 }
668 if (refine->target_type & (LYS_LIST | LYS_LEAFLIST)) {
669 if (refine->flags & LYS_RFN_MINSET) {
670 yin_print_close_parent(out, &content);
671 yin_print_unsigned(out, level, LYEXT_SUBSTMT_MIN, 0, module, refine->ext, refine->ext_size,
672 refine->mod.list.min);
673 }
674 if (refine->flags & LYS_RFN_MAXSET) {
675 yin_print_close_parent(out, &content);
676 if (refine->mod.list.max) {
677 yin_print_unsigned(out, level, LYEXT_SUBSTMT_MAX, 0, module, refine->ext, refine->ext_size,
678 refine->mod.list.max);
679 } else {
680 yin_print_substmt(out, level, LYEXT_SUBSTMT_MAX, 0, "unbounded", module,
681 refine->ext, refine->ext_size);
682 }
683 }
684 }
685 yin_print_snode_common(out, level, (struct lys_node *)refine, module, &content,
686 SNODE_COMMON_DSC | SNODE_COMMON_REF);
687 level--;
688
689 yin_print_close(out, level, NULL, "refine", content);
690 }
691
692 static void
yin_print_deviation(struct lyout * out,int level,const struct lys_module * module,const struct lys_deviation * deviation)693 yin_print_deviation(struct lyout *out, int level, const struct lys_module *module,
694 const struct lys_deviation *deviation)
695 {
696 int i, j, p, content;
697 const char *str;
698
699 str = transform_json2schema(module, deviation->target_name);
700 yin_print_open(out, level, NULL, "deviation", "target-node", str, 1);
701 lydict_remove(module->ctx, str);
702
703 level++;
704
705 if (deviation->ext_size) {
706 yin_print_extension_instances(out, level, module, LYEXT_SUBSTMT_SELF, 0, deviation->ext, deviation->ext_size);
707 }
708 yin_print_substmt(out, level, LYEXT_SUBSTMT_DESCRIPTION, 0, deviation->dsc,
709 module, deviation->ext, deviation->ext_size);
710 yin_print_substmt(out, level, LYEXT_SUBSTMT_REFERENCE, 0, deviation->ref,
711 module, deviation->ext, deviation->ext_size);
712
713 for (i = 0; i < deviation->deviate_size; ++i) {
714 ly_print(out, "%*s<deviate value=", LEVEL, INDENT);
715 if (deviation->deviate[i].mod == LY_DEVIATE_NO) {
716 if (deviation->deviate[i].ext_size) {
717 ly_print(out, "\"not-supported\">\n");
718 } else {
719 ly_print(out, "\"not-supported\"/>\n");
720 continue;
721 }
722 } else if (deviation->deviate[i].mod == LY_DEVIATE_ADD) {
723 ly_print(out, "\"add\">\n");
724 } else if (deviation->deviate[i].mod == LY_DEVIATE_RPL) {
725 ly_print(out, "\"replace\">\n");
726 } else if (deviation->deviate[i].mod == LY_DEVIATE_DEL) {
727 ly_print(out, "\"delete\">\n");
728 }
729 level++;
730
731 /* extensions */
732 if (deviation->deviate[i].ext_size) {
733 yin_print_extension_instances(out, level, module, LYEXT_SUBSTMT_SELF, 0,
734 deviation->deviate[i].ext, deviation->deviate[i].ext_size);
735 }
736
737 /* type */
738 if (deviation->deviate[i].type) {
739 yin_print_type(out, level, module, deviation->deviate[i].type);
740 }
741
742 /* units */
743 yin_print_substmt(out, level, LYEXT_SUBSTMT_UNITS, 0, deviation->deviate[i].units, module,
744 deviation->deviate[i].ext, deviation->deviate[i].ext_size);
745
746 /* must */
747 for (j = 0; j < deviation->deviate[i].must_size; ++j) {
748 yin_print_must(out, level, module, &deviation->deviate[i].must[j]);
749 }
750
751 /* unique */
752 for (j = 0; j < deviation->deviate[i].unique_size; ++j) {
753 yin_print_unique(out, level, module, &deviation->deviate[i].unique[j]);
754 content = 0;
755 /* unique's extensions */
756 p = -1;
757 do {
758 p = lys_ext_iter(deviation->deviate[i].ext, deviation->deviate[i].ext_size,
759 p + 1, LYEXT_SUBSTMT_UNIQUE);
760 } while (p != -1 && deviation->deviate[i].ext[p]->insubstmt_index != j);
761 if (p != -1) {
762 yin_print_close_parent(out, &content);
763 do {
764 yin_print_extension_instances(out, level + 1, module, LYEXT_SUBSTMT_UNIQUE, j,
765 &deviation->deviate[i].ext[p], 1);
766 do {
767 p = lys_ext_iter(deviation->deviate[i].ext, deviation->deviate[i].ext_size,
768 p + 1, LYEXT_SUBSTMT_UNIQUE);
769 } while (p != -1 && deviation->deviate[i].ext[p]->insubstmt_index != j);
770 } while (p != -1);
771 }
772 yin_print_close(out, level, NULL, "unique", content);
773 }
774
775 /* default */
776 for (j = 0; j < deviation->deviate[i].dflt_size; ++j) {
777 yin_print_substmt(out, level, LYEXT_SUBSTMT_DEFAULT, j, deviation->deviate[i].dflt[j], module,
778 deviation->deviate[i].ext, deviation->deviate[i].ext_size);
779 }
780
781 /* config */
782 if (deviation->deviate[i].flags & LYS_CONFIG_W) {
783 yin_print_substmt(out, level, LYEXT_SUBSTMT_CONFIG, 0, "true", module,
784 deviation->deviate->ext, deviation->deviate[i].ext_size);
785 } else if (deviation->deviate[i].flags & LYS_CONFIG_R) {
786 yin_print_substmt(out, level, LYEXT_SUBSTMT_CONFIG, 0, "false", module,
787 deviation->deviate->ext, deviation->deviate[i].ext_size);
788 }
789
790 /* mandatory */
791 if (deviation->deviate[i].flags & LYS_MAND_TRUE) {
792 yin_print_substmt(out, level, LYEXT_SUBSTMT_MANDATORY, 0, "true", module,
793 deviation->deviate[i].ext, deviation->deviate[i].ext_size);
794 } else if (deviation->deviate[i].flags & LYS_MAND_FALSE) {
795 yin_print_substmt(out, level, LYEXT_SUBSTMT_MANDATORY, 0, "false", module,
796 deviation->deviate[i].ext, deviation->deviate[i].ext_size);
797 }
798
799 /* min-elements */
800 if (deviation->deviate[i].min_set) {
801 yin_print_unsigned(out, level, LYEXT_SUBSTMT_MIN, 0, module,
802 deviation->deviate[i].ext, deviation->deviate[i].ext_size,
803 deviation->deviate[i].min);
804 }
805
806 /* max-elements */
807 if (deviation->deviate[i].max_set) {
808 if (deviation->deviate[i].max) {
809 yin_print_unsigned(out, level, LYEXT_SUBSTMT_MAX, 0, module,
810 deviation->deviate[i].ext, deviation->deviate[i].ext_size,
811 deviation->deviate[i].max);
812 } else {
813 yin_print_substmt(out, level, LYEXT_SUBSTMT_MAX, 0, "unbounded", module,
814 deviation->deviate[i].ext, deviation->deviate[i].ext_size);
815 }
816 }
817 level--;
818
819 yin_print_close(out, level, NULL, "deviate", 1);
820 }
821
822 level--;
823 yin_print_close(out, level, NULL, "deviation", 1);
824 }
825
826 static void
yin_print_augment(struct lyout * out,int level,const struct lys_module * module,const struct lys_node_augment * augment)827 yin_print_augment(struct lyout *out, int level, const struct lys_module *module,
828 const struct lys_node_augment *augment)
829 {
830 struct lys_node *sub;
831 const char *str;
832
833 str = transform_json2schema(module, augment->target_name);
834 yin_print_open(out, level, NULL, "augment", "target-node", str, 1);
835 lydict_remove(module->ctx, str);
836 level++;
837
838 yin_print_snode_common(out, level, (struct lys_node *)augment, augment->module, NULL, SNODE_COMMON_EXT);
839 if (augment->when) {
840 yin_print_when(out, level, module, augment->when);
841 }
842 yin_print_snode_common(out, level, (struct lys_node *)augment, augment->module, NULL,
843 SNODE_COMMON_IFF | SNODE_COMMON_STATUS | SNODE_COMMON_DSC | SNODE_COMMON_REF);
844
845
846 LY_TREE_FOR(augment->child, sub) {
847 /* only our augment */
848 if (sub->parent != (struct lys_node *)augment) {
849 continue;
850 }
851 yin_print_snode(out, level, sub,
852 LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
853 LYS_USES | LYS_ANYDATA | LYS_CASE | LYS_ACTION | LYS_NOTIF);
854 }
855 level--;
856
857 yin_print_close(out, level, NULL, "augment", 1);
858 }
859
860 static void
yin_print_typedef(struct lyout * out,int level,const struct lys_module * module,const struct lys_tpdf * tpdf)861 yin_print_typedef(struct lyout *out, int level, const struct lys_module *module, const struct lys_tpdf *tpdf)
862 {
863 const char *dflt;
864
865 yin_print_open(out, level, NULL, "typedef", "name", tpdf->name, 1);
866 level++;
867
868 yin_print_snode_common(out, level, (struct lys_node *)tpdf, module, NULL, SNODE_COMMON_EXT);
869 yin_print_type(out, level, module, &tpdf->type);
870 if (tpdf->units) {
871 yin_print_substmt(out, level, LYEXT_SUBSTMT_UNITS, 0, tpdf->units, module, tpdf->ext, tpdf->ext_size);
872 }
873 if (tpdf->dflt) {
874 if (tpdf->flags & LYS_DFLTJSON) {
875 assert(strchr(tpdf->dflt, ':'));
876 if (!strncmp(tpdf->dflt, module->name, strchr(tpdf->dflt, ':') - tpdf->dflt)) {
877 /* local module */
878 dflt = lydict_insert(module->ctx, strchr(tpdf->dflt, ':') + 1, 0);
879 } else {
880 dflt = transform_json2schema(module, tpdf->dflt);
881 }
882 } else {
883 dflt = tpdf->dflt;
884 }
885 yin_print_substmt(out, level, LYEXT_SUBSTMT_DEFAULT, 0, dflt, module, tpdf->ext, tpdf->ext_size);
886 if (tpdf->flags & LYS_DFLTJSON) {
887 lydict_remove(module->ctx, dflt);
888 }
889 }
890 yin_print_snode_common(out, level, (struct lys_node *)tpdf, module, NULL,
891 SNODE_COMMON_STATUS | SNODE_COMMON_DSC | SNODE_COMMON_REF);
892
893 level--;
894 yin_print_close(out, level, NULL, "typedef", 1);
895 }
896
897 static void
yin_print_identity(struct lyout * out,int level,const struct lys_ident * ident)898 yin_print_identity(struct lyout *out, int level, const struct lys_ident *ident)
899 {
900 int content = 0, i;
901 struct lys_module *mod;
902 char *str;
903
904 yin_print_open(out, level, NULL, "identity", "name", ident->name, content);
905 level++;
906
907 yin_print_snode_common(out, level, (struct lys_node *)ident, ident->module, &content,
908 SNODE_COMMON_EXT | SNODE_COMMON_IFF);
909 for (i = 0; i < ident->base_size; i++) {
910 yin_print_close_parent(out, &content);
911 mod = lys_main_module(ident->base[i]->module);
912 if (lys_main_module(ident->module) == mod) {
913 yin_print_substmt(out, level, LYEXT_SUBSTMT_BASE, i, ident->base[i]->name,
914 ident->module, ident->ext, ident->ext_size);
915 } else {
916 if (asprintf(&str, "%s:%s", transform_module_name2import_prefix(ident->module, mod->name), ident->base[i]->name) == -1) {
917 LOGMEM(mod->ctx);
918 } else {
919 yin_print_substmt(out, level, LYEXT_SUBSTMT_BASE, i, str,
920 ident->module, ident->ext, ident->ext_size);
921 free(str);
922 }
923 }
924 }
925 yin_print_snode_common(out, level, (struct lys_node *)ident, ident->module, &content,
926 SNODE_COMMON_STATUS | SNODE_COMMON_DSC | SNODE_COMMON_REF);
927
928 level--;
929 yin_print_close(out, level, NULL, "identity", content);
930 }
931
932 static void
yin_print_container(struct lyout * out,int level,const struct lys_node * node)933 yin_print_container(struct lyout *out, int level, const struct lys_node *node)
934 {
935 int i, content = 0;
936 struct lys_node *sub;
937 struct lys_node_container *cont = (struct lys_node_container *)node;
938
939 yin_print_open(out, level, NULL, "container", "name", node->name, content);
940 level++;
941
942 yin_print_snode_common(out, level, node, node->module, &content, SNODE_COMMON_EXT);
943 if (cont->when) {
944 yin_print_close_parent(out, &content);
945 yin_print_when(out, level, node->module, cont->when);
946 }
947
948 for (i = 0; i < cont->iffeature_size; i++) {
949 yin_print_close_parent(out, &content);
950 yin_print_iffeature(out, level, node->module, &cont->iffeature[i]);
951 }
952
953 for (i = 0; i < cont->must_size; i++) {
954 yin_print_close_parent(out, &content);
955 yin_print_must(out, level, node->module, &cont->must[i]);
956 }
957
958 if (cont->presence) {
959 yin_print_close_parent(out, &content);
960 yin_print_substmt(out, level, LYEXT_SUBSTMT_PRESENCE, 0, cont->presence,
961 node->module, node->ext, node->ext_size);
962 }
963 yin_print_snode_common(out, level, node, node->module, &content, SNODE_COMMON_CONFIG |
964 SNODE_COMMON_STATUS | SNODE_COMMON_DSC | SNODE_COMMON_REF);
965
966 for (i = 0; i < cont->tpdf_size; i++) {
967 yin_print_close_parent(out, &content);
968 yin_print_typedef(out, level, node->module, &cont->tpdf[i]);
969 }
970
971 LY_TREE_FOR(node->child, sub) {
972 /* augments */
973 if (sub->parent != node) {
974 continue;
975 }
976 yin_print_close_parent(out, &content);
977 yin_print_snode(out, level, sub, LYS_GROUPING);
978 }
979 LY_TREE_FOR(node->child, sub) {
980 /* augments */
981 if (sub->parent != node) {
982 continue;
983 }
984 yin_print_close_parent(out, &content);
985 yin_print_snode(out, level, sub, LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
986 LYS_USES | LYS_ANYDATA );
987 }
988 LY_TREE_FOR(node->child, sub) {
989 /* augments */
990 if (sub->parent != node) {
991 continue;
992 }
993 yin_print_close_parent(out, &content);
994 yin_print_snode(out, level, sub, LYS_ACTION);
995 }
996 LY_TREE_FOR(node->child, sub) {
997 /* augments */
998 if (sub->parent != node) {
999 continue;
1000 }
1001 yin_print_close_parent(out, &content);
1002 yin_print_snode(out, level, sub, LYS_NOTIF);
1003 }
1004
1005 level--;
1006 yin_print_close(out, level, NULL, "container", content);
1007 }
1008
1009 static void
yin_print_case(struct lyout * out,int level,const struct lys_node * node)1010 yin_print_case(struct lyout *out, int level, const struct lys_node *node)
1011 {
1012 int content = 0;
1013 struct lys_node *sub;
1014 struct lys_node_case *cas = (struct lys_node_case *)node;
1015
1016 if (!(node->flags & LYS_IMPLICIT)) {
1017 yin_print_open(out, level, NULL, "case", "name", cas->name, content);
1018 level++;
1019
1020 yin_print_snode_common(out, level, node, node->module, &content, SNODE_COMMON_EXT);
1021 if (cas->when) {
1022 yin_print_close_parent(out, &content);
1023 yin_print_when(out, level, node->module, cas->when);
1024 }
1025 yin_print_snode_common(out, level, node, node->module, &content,
1026 SNODE_COMMON_IFF | SNODE_COMMON_STATUS | SNODE_COMMON_DSC | SNODE_COMMON_REF);
1027 } else {
1028 content = 1;
1029 }
1030
1031 /* print children */
1032 LY_TREE_FOR(node->child, sub) {
1033 /* augments */
1034 if (sub->parent != node) {
1035 continue;
1036 }
1037 yin_print_close_parent(out, &content);
1038 yin_print_snode(out, level, sub,
1039 LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
1040 LYS_USES | LYS_ANYDATA);
1041 }
1042
1043 if (node->flags & LYS_IMPLICIT) {
1044 /* do not print anything about the case, it was implicitely added by libyang */
1045 return;
1046 }
1047
1048 level--;
1049 yin_print_close(out, level, NULL, "case", content);
1050 }
1051
1052 static void
yin_print_choice(struct lyout * out,int level,const struct lys_node * node)1053 yin_print_choice(struct lyout *out, int level, const struct lys_node *node)
1054 {
1055 int i, content = 0;
1056 struct lys_node *sub;
1057 struct lys_node_choice *choice = (struct lys_node_choice *)node;
1058
1059 yin_print_open(out, level, NULL, "choice", "name", node->name, content);
1060 level++;
1061
1062 yin_print_snode_common(out, level, node, node->module, &content, SNODE_COMMON_EXT);
1063 if (choice->when) {
1064 yin_print_close_parent(out, &content);
1065 yin_print_when(out, level, node->module, choice->when);
1066 }
1067 for (i = 0; i < choice->iffeature_size; i++) {
1068 yin_print_close_parent(out, &content);
1069 yin_print_iffeature(out, level, node->module, &choice->iffeature[i]);
1070 }
1071 if (choice->dflt) {
1072 yin_print_close_parent(out, &content);
1073 yin_print_substmt(out, level, LYEXT_SUBSTMT_DEFAULT, 0, choice->dflt->name,
1074 node->module, node->ext, node->ext_size);
1075 }
1076
1077 yin_print_snode_common(out, level, node, node->module, &content, SNODE_COMMON_CONFIG | SNODE_COMMON_MAND |
1078 SNODE_COMMON_STATUS | SNODE_COMMON_DSC | SNODE_COMMON_REF);
1079
1080 LY_TREE_FOR(node->child, sub) {
1081 /* augments */
1082 if (sub->parent != node) {
1083 continue;
1084 }
1085 yin_print_close_parent(out, &content);
1086 yin_print_snode(out, level, sub,
1087 LYS_CHOICE |LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA | LYS_CASE);
1088 }
1089
1090 level--;
1091 yin_print_close(out, level, NULL, "choice", content);
1092 }
1093
1094 static void
yin_print_leaf(struct lyout * out,int level,const struct lys_node * node)1095 yin_print_leaf(struct lyout *out, int level, const struct lys_node *node)
1096 {
1097 int i;
1098 struct lys_node_leaf *leaf = (struct lys_node_leaf *)node;
1099 const char *dflt;
1100
1101 yin_print_open(out, level, NULL, "leaf", "name", node->name, 1);
1102 level++;
1103
1104 yin_print_snode_common(out, level, node, node->module, NULL, SNODE_COMMON_EXT);
1105 if (leaf->when) {
1106 yin_print_when(out, level, node->module, leaf->when);
1107 }
1108 for (i = 0; i < leaf->iffeature_size; i++) {
1109 yin_print_iffeature(out, level, node->module, &leaf->iffeature[i]);
1110 }
1111 yin_print_type(out, level, node->module, &leaf->type);
1112 yin_print_substmt(out, level, LYEXT_SUBSTMT_UNITS, 0, leaf->units,
1113 node->module, node->ext, node->ext_size);
1114 for (i = 0; i < leaf->must_size; i++) {
1115 yin_print_must(out, level, node->module, &leaf->must[i]);
1116 }
1117 if (leaf->dflt) {
1118 if (leaf->flags & LYS_DFLTJSON) {
1119 assert(strchr(leaf->dflt, ':'));
1120 if (!strncmp(leaf->dflt, lys_node_module(node)->name, strchr(leaf->dflt, ':') - leaf->dflt)) {
1121 /* local module */
1122 dflt = lydict_insert(node->module->ctx, strchr(leaf->dflt, ':') + 1, 0);
1123 } else {
1124 dflt = transform_json2schema(node->module, leaf->dflt);
1125 }
1126 } else {
1127 dflt = leaf->dflt;
1128 }
1129 yin_print_substmt(out, level, LYEXT_SUBSTMT_DEFAULT, 0, dflt,
1130 node->module, node->ext, node->ext_size);
1131 if (leaf->flags & LYS_DFLTJSON) {
1132 lydict_remove(node->module->ctx, dflt);
1133 }
1134 }
1135 yin_print_snode_common(out, level, node, node->module, NULL, SNODE_COMMON_CONFIG | SNODE_COMMON_MAND |
1136 SNODE_COMMON_STATUS | SNODE_COMMON_DSC | SNODE_COMMON_REF);
1137
1138 level--;
1139 yin_print_close(out, level, NULL, "leaf", 1);
1140 }
1141
1142 static void
yin_print_anydata(struct lyout * out,int level,const struct lys_node * node)1143 yin_print_anydata(struct lyout *out, int level, const struct lys_node *node)
1144 {
1145 int i, content = 0;
1146 struct lys_node_anydata *any = (struct lys_node_anydata *)node;
1147 const char *name;
1148
1149 if (!lys_parent(node) && !strcmp(node->name, "config") && !strcmp(node->module->name, "ietf-netconf")) {
1150 /* node added by libyang, not actually in the model */
1151 return;
1152 }
1153
1154 name = any->nodetype == LYS_ANYXML ? "anyxml" : "anydata";
1155 yin_print_open(out, level, NULL, name, "name", any->name, content);
1156
1157 level++;
1158 yin_print_snode_common(out, level, node, node->module, &content, SNODE_COMMON_EXT);
1159 if (any->when) {
1160 yin_print_close_parent(out, &content);
1161 yin_print_when(out, level, node->module, any->when);
1162 }
1163 for (i = 0; i < any->iffeature_size; i++) {
1164 yin_print_close_parent(out, &content);
1165 yin_print_iffeature(out, level, node->module, &any->iffeature[i]);
1166 }
1167 for (i = 0; i < any->must_size; i++) {
1168 yin_print_close_parent(out, &content);
1169 yin_print_must(out, level, node->module, &any->must[i]);
1170 }
1171 yin_print_snode_common(out, level, node, node->module, &content, SNODE_COMMON_CONFIG | SNODE_COMMON_MAND |
1172 SNODE_COMMON_STATUS | SNODE_COMMON_DSC | SNODE_COMMON_REF);
1173
1174 level--;
1175 yin_print_close(out, level, NULL, name, content);
1176 }
1177
1178 static void
yin_print_leaflist(struct lyout * out,int level,const struct lys_node * node)1179 yin_print_leaflist(struct lyout *out, int level, const struct lys_node *node)
1180 {
1181 int i;
1182 struct lys_node_leaflist *llist = (struct lys_node_leaflist *)node;
1183 const char *dflt;
1184
1185 yin_print_open(out, level, NULL, "leaf-list", "name", node->name, 1);
1186 level++;
1187
1188 yin_print_snode_common(out, level, node, node->module, NULL, SNODE_COMMON_EXT);
1189 if (llist->when) {
1190 yin_print_when(out, level, llist->module, llist->when);
1191 }
1192 for (i = 0; i < llist->iffeature_size; i++) {
1193 yin_print_iffeature(out, level, node->module, &llist->iffeature[i]);
1194 }
1195 yin_print_type(out, level, node->module, &llist->type);
1196 yin_print_substmt(out, level, LYEXT_SUBSTMT_UNITS, 0, llist->units,
1197 node->module, node->ext, node->ext_size);
1198 for (i = 0; i < llist->must_size; i++) {
1199 yin_print_must(out, level, node->module, &llist->must[i]);
1200 }
1201 for (i = 0; i < llist->dflt_size; i++) {
1202 if (llist->flags & LYS_DFLTJSON) {
1203 assert(strchr(llist->dflt[i], ':'));
1204 if (!strncmp(llist->dflt[i], lys_node_module(node)->name, strchr(llist->dflt[i], ':') - llist->dflt[i])) {
1205 /* local module */
1206 dflt = lydict_insert(node->module->ctx, strchr(llist->dflt[i], ':') + 1, 0);
1207 } else {
1208 dflt = transform_json2schema(node->module, llist->dflt[i]);
1209 }
1210 } else {
1211 dflt = llist->dflt[i];
1212 }
1213 yin_print_substmt(out, level, LYEXT_SUBSTMT_DEFAULT, i, dflt,
1214 node->module, node->ext, node->ext_size);
1215 if (llist->flags & LYS_DFLTJSON) {
1216 lydict_remove(node->module->ctx, dflt);
1217 }
1218 }
1219 yin_print_snode_common(out, level, node, node->module, NULL, SNODE_COMMON_CONFIG);
1220 if (llist->min > 0) {
1221 yin_print_unsigned(out, level, LYEXT_SUBSTMT_MIN, 0, node->module, node->ext, node->ext_size, llist->min);
1222 }
1223 if (llist->max > 0) {
1224 yin_print_unsigned(out, level, LYEXT_SUBSTMT_MAX, 0, node->module, node->ext, node->ext_size, llist->max);
1225 }
1226 if (llist->flags & LYS_USERORDERED) {
1227 yin_print_substmt(out, level, LYEXT_SUBSTMT_ORDEREDBY, 0, "user",
1228 node->module, node->ext, node->ext_size);
1229 } else if (lys_ext_iter(node->ext, node->ext_size, 0, LYEXT_SUBSTMT_ORDEREDBY) != -1) {
1230 yin_print_substmt(out, level, LYEXT_SUBSTMT_ORDEREDBY, 0, "system",
1231 node->module, node->ext, node->ext_size);
1232 }
1233 yin_print_snode_common(out, level, node, node->module, NULL,
1234 SNODE_COMMON_STATUS | SNODE_COMMON_DSC | SNODE_COMMON_REF);
1235
1236 level--;
1237 yin_print_close(out, level, NULL, "leaf-list", 1);
1238 }
1239
1240 static void
yin_print_list(struct lyout * out,int level,const struct lys_node * node)1241 yin_print_list(struct lyout *out, int level, const struct lys_node *node)
1242 {
1243 int i, p, content = 0, content2;
1244 struct lys_node *sub;
1245 struct lys_node_list *list = (struct lys_node_list *)node;
1246
1247 yin_print_open(out, level, NULL, "list", "name", node->name, content);
1248 level++;
1249
1250 yin_print_snode_common(out, level, node, node->module, &content, SNODE_COMMON_EXT);
1251 if (list->when) {
1252 yin_print_close_parent(out, &content);
1253 yin_print_when(out, level, list->module, list->when);
1254 }
1255 for (i = 0; i < list->iffeature_size; i++) {
1256 yin_print_close_parent(out, &content);
1257 yin_print_iffeature(out, level, node->module, &list->iffeature[i]);
1258 }
1259 for (i = 0; i < list->must_size; i++) {
1260 yin_print_close_parent(out, &content);
1261 yin_print_must(out, level, list->module, &list->must[i]);
1262 }
1263 if (list->keys_size) {
1264 yin_print_close_parent(out, &content);
1265 yin_print_substmt(out, level, LYEXT_SUBSTMT_KEY, 0, list->keys_str,
1266 node->module, node->ext, node->ext_size);
1267 }
1268 for (i = 0; i < list->unique_size; i++) {
1269 yin_print_close_parent(out, &content);
1270 yin_print_unique(out, level, node->module, &list->unique[i]);
1271 content2 = 0;
1272 /* unique's extensions */
1273 p = -1;
1274 do {
1275 p = lys_ext_iter(list->ext, list->ext_size, p + 1, LYEXT_SUBSTMT_UNIQUE);
1276 } while (p != -1 && list->ext[p]->insubstmt_index != i);
1277 if (p != -1) {
1278 yin_print_close_parent(out, &content2);
1279 do {
1280 yin_print_extension_instances(out, level + 1, list->module, LYEXT_SUBSTMT_UNIQUE, i, &list->ext[p], 1);
1281 do {
1282 p = lys_ext_iter(list->ext, list->ext_size, p + 1, LYEXT_SUBSTMT_UNIQUE);
1283 } while (p != -1 && list->ext[p]->insubstmt_index != i);
1284 } while (p != -1);
1285 }
1286 yin_print_close(out, level, NULL, "unique", content2);
1287 }
1288 yin_print_snode_common(out, level, node, node->module, &content, SNODE_COMMON_CONFIG);
1289 if (list->min > 0) {
1290 yin_print_close_parent(out, &content);
1291 yin_print_unsigned(out, level, LYEXT_SUBSTMT_MIN, 0, node->module, node->ext, node->ext_size, list->min);
1292 }
1293 if (list->max > 0) {
1294 yin_print_close_parent(out, &content);
1295 yin_print_unsigned(out, level, LYEXT_SUBSTMT_MAX, 0, node->module, node->ext, node->ext_size, list->max);
1296 }
1297 if (list->flags & LYS_USERORDERED) {
1298 yin_print_close_parent(out, &content);
1299 yin_print_substmt(out, level, LYEXT_SUBSTMT_ORDEREDBY, 0, "user",
1300 node->module, node->ext, node->ext_size);
1301 } else if (lys_ext_iter(node->ext, node->ext_size, 0, LYEXT_SUBSTMT_ORDEREDBY) != -1) {
1302 yin_print_close_parent(out, &content);
1303 yin_print_substmt(out, level, LYEXT_SUBSTMT_ORDEREDBY, 0, "system",
1304 node->module, node->ext, node->ext_size);
1305 }
1306 yin_print_snode_common(out, level, node, node->module, &content,
1307 SNODE_COMMON_STATUS | SNODE_COMMON_DSC | SNODE_COMMON_REF);
1308 for (i = 0; i < list->tpdf_size; i++) {
1309 yin_print_close_parent(out, &content);
1310 yin_print_typedef(out, level, list->module, &list->tpdf[i]);
1311 }
1312
1313 LY_TREE_FOR(node->child, sub) {
1314 /* augments */
1315 if (sub->parent != node) {
1316 continue;
1317 }
1318 yin_print_close_parent(out, &content);
1319 yin_print_snode(out, level, sub, LYS_GROUPING);
1320 }
1321
1322 LY_TREE_FOR(node->child, sub) {
1323 /* augments */
1324 if (sub->parent != node) {
1325 continue;
1326 }
1327 yin_print_close_parent(out, &content);
1328 yin_print_snode(out, level, sub, LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
1329 LYS_USES | LYS_ANYDATA);
1330 }
1331
1332 LY_TREE_FOR(node->child, sub) {
1333 /* augments */
1334 if (sub->parent != node) {
1335 continue;
1336 }
1337 yin_print_close_parent(out, &content);
1338 yin_print_snode(out, level, sub, LYS_ACTION);
1339 }
1340
1341 LY_TREE_FOR(node->child, sub) {
1342 /* augments */
1343 if (sub->parent != node) {
1344 continue;
1345 }
1346 yin_print_close_parent(out, &content);
1347 yin_print_snode(out, level, sub, LYS_NOTIF);
1348 }
1349
1350 level--;
1351 yin_print_close(out, level, NULL, "list", content);
1352 }
1353
1354 static void
yin_print_grouping(struct lyout * out,int level,const struct lys_node * node)1355 yin_print_grouping(struct lyout *out, int level, const struct lys_node *node)
1356 {
1357 int i, content = 0;
1358 struct lys_node *sub;
1359 struct lys_node_grp *grp = (struct lys_node_grp *)node;
1360
1361 yin_print_open(out, level, NULL, "grouping", "name", node->name, content);
1362 level++;
1363
1364 yin_print_snode_common(out, level, node, node->module, &content, SNODE_COMMON_EXT | SNODE_COMMON_STATUS |
1365 SNODE_COMMON_DSC | SNODE_COMMON_REF);
1366
1367 for (i = 0; i < grp->tpdf_size; i++) {
1368 yin_print_close_parent(out, &content);
1369 yin_print_typedef(out, level, node->module, &grp->tpdf[i]);
1370 }
1371
1372 LY_TREE_FOR(node->child, sub) {
1373 yin_print_close_parent(out, &content);
1374 yin_print_snode(out, level, sub, LYS_GROUPING);
1375 }
1376
1377 LY_TREE_FOR(node->child, sub) {
1378 yin_print_close_parent(out, &content);
1379 yin_print_snode(out, level, sub, LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
1380 LYS_USES | LYS_ANYDATA);
1381 }
1382
1383 LY_TREE_FOR(node->child, sub) {
1384 yin_print_close_parent(out, &content);
1385 yin_print_snode(out, level, sub, LYS_ACTION);
1386 }
1387
1388 LY_TREE_FOR(node->child, sub) {
1389 yin_print_close_parent(out, &content);
1390 yin_print_snode(out, level, sub, LYS_NOTIF);
1391 }
1392
1393 level--;
1394 yin_print_close(out, level, NULL, "grouping", content);
1395 }
1396
1397 static void
yin_print_uses(struct lyout * out,int level,const struct lys_node * node)1398 yin_print_uses(struct lyout *out, int level, const struct lys_node *node)
1399 {
1400 int i, content = 0;
1401 struct lys_node_uses *uses = (struct lys_node_uses *)node;
1402 struct lys_module *mod;
1403
1404 ly_print(out, "%*s<uses name=\"", LEVEL, INDENT);
1405 if (node->child) {
1406 mod = lys_node_module(node->child);
1407 if (lys_node_module(node) != mod) {
1408 ly_print(out, "%s:", transform_module_name2import_prefix(node->module, mod->name));
1409 }
1410 }
1411 ly_print(out, "%s\"", uses->name);
1412 level++;
1413
1414 yin_print_snode_common(out, level, node, node->module, &content, SNODE_COMMON_EXT);
1415 if (uses->when) {
1416 yin_print_close_parent(out, &content);
1417 yin_print_when(out, level, node->module, uses->when);
1418 }
1419 yin_print_snode_common(out, level, node, node->module, &content, SNODE_COMMON_IFF |
1420 SNODE_COMMON_STATUS | SNODE_COMMON_DSC | SNODE_COMMON_REF);
1421 for (i = 0; i < uses->refine_size; i++) {
1422 yin_print_close_parent(out, &content);
1423 yin_print_refine(out, level, node->module, &uses->refine[i]);
1424 }
1425 for (i = 0; i < uses->augment_size; i++) {
1426 yin_print_close_parent(out, &content);
1427 yin_print_augment(out, level, node->module, &uses->augment[i]);
1428 }
1429
1430 level--;
1431 yin_print_close(out, level, NULL, "uses", content);
1432 }
1433
1434 static void
yin_print_input_output(struct lyout * out,int level,const struct lys_node * node)1435 yin_print_input_output(struct lyout *out, int level, const struct lys_node *node)
1436 {
1437 int i;
1438 struct lys_node *sub;
1439 struct lys_node_inout *inout = (struct lys_node_inout *)node;
1440
1441 yin_print_open(out, level, NULL, inout->nodetype == LYS_INPUT ? "input" : "output", NULL, NULL, 1);
1442 level++;
1443
1444 if (inout->ext_size) {
1445 yin_print_extension_instances(out, level, node->module, LYEXT_SUBSTMT_SELF, 0, inout->ext, inout->ext_size);
1446 }
1447 for (i = 0; i < inout->must_size; i++) {
1448 yin_print_must(out, level, node->module, &inout->must[i]);
1449 }
1450 for (i = 0; i < inout->tpdf_size; i++) {
1451 yin_print_typedef(out, level, node->module, &inout->tpdf[i]);
1452 }
1453
1454 LY_TREE_FOR(node->child, sub) {
1455 /* augments */
1456 if (sub->parent != node) {
1457 continue;
1458 }
1459 yin_print_snode(out, level, sub, LYS_GROUPING);
1460 }
1461 LY_TREE_FOR(node->child, sub) {
1462 /* augments */
1463 if (sub->parent != node) {
1464 continue;
1465 }
1466 yin_print_snode(out, level, sub, LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
1467 LYS_USES | LYS_ANYDATA);
1468 }
1469 level--;
1470
1471 yin_print_close(out, level, NULL, (inout->nodetype == LYS_INPUT ? "input" : "output"), 1);
1472 }
1473
1474 static void
yin_print_rpc_action(struct lyout * out,int level,const struct lys_node * node)1475 yin_print_rpc_action(struct lyout *out, int level, const struct lys_node *node)
1476 {
1477 int i, content = 0;
1478 struct lys_node *sub;
1479 struct lys_node_rpc_action *rpc = (struct lys_node_rpc_action *)node;
1480
1481 yin_print_open(out, level, NULL, (node->nodetype == LYS_RPC ? "rpc" : "action"), "name", node->name, content);
1482 level++;
1483
1484 yin_print_snode_common(out, level, node, node->module, &content, SNODE_COMMON_EXT | SNODE_COMMON_IFF |
1485 SNODE_COMMON_STATUS | SNODE_COMMON_DSC | SNODE_COMMON_REF);
1486
1487 for (i = 0; i < rpc->tpdf_size; i++) {
1488 yin_print_close_parent(out, &content);
1489 yin_print_typedef(out, level, node->module, &rpc->tpdf[i]);
1490 }
1491
1492 LY_TREE_FOR(node->child, sub) {
1493 /* augments */
1494 if ((sub->parent != node) || (((sub->nodetype & (LYS_INPUT | LYS_OUTPUT)) && (sub->flags & LYS_IMPLICIT)))) {
1495 continue;
1496 }
1497 yin_print_close_parent(out, &content);
1498 yin_print_snode(out, level, sub, LYS_INPUT | LYS_OUTPUT | LYS_GROUPING);
1499 }
1500
1501 level--;
1502 yin_print_close(out, level, NULL, (node->nodetype == LYS_RPC ? "rpc" : "action"), content);
1503 }
1504
1505 static void
yin_print_notif(struct lyout * out,int level,const struct lys_node * node)1506 yin_print_notif(struct lyout *out, int level, const struct lys_node *node)
1507 {
1508 int i, content = 0;
1509 struct lys_node *sub;
1510 struct lys_node_notif *notif = (struct lys_node_notif *)node;
1511
1512 yin_print_open(out, level, NULL, "notification", "name", node->name, content);
1513 level++;
1514
1515 yin_print_snode_common(out, level, node, node->module, &content, SNODE_COMMON_EXT | SNODE_COMMON_IFF);
1516 for (i = 0; i < notif->must_size; i++) {
1517 yin_print_close_parent(out, &content);
1518 yin_print_must(out, level, node->module, ¬if->must[i]);
1519 }
1520 yin_print_snode_common(out, level, node, node->module, &content,
1521 SNODE_COMMON_STATUS | SNODE_COMMON_DSC | SNODE_COMMON_REF);
1522 for (i = 0; i < notif->tpdf_size; i++) {
1523 yin_print_close_parent(out, &content);
1524 yin_print_typedef(out, level, node->module, ¬if->tpdf[i]);
1525 }
1526
1527 LY_TREE_FOR(node->child, sub) {
1528 /* augments */
1529 if (sub->parent != node) {
1530 continue;
1531 }
1532 yin_print_close_parent(out, &content);
1533 yin_print_snode(out, level, sub, LYS_GROUPING);
1534 }
1535 LY_TREE_FOR(node->child, sub) {
1536 /* augments */
1537 if (sub->parent != node) {
1538 continue;
1539 }
1540 yin_print_close_parent(out, &content);
1541 yin_print_snode(out, level, sub,
1542 LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
1543 LYS_USES | LYS_ANYDATA);
1544 }
1545
1546 level--;
1547 yin_print_close(out, level, NULL, "notification", content);
1548 }
1549
1550 static void
yin_print_snode(struct lyout * out,int level,const struct lys_node * node,int mask)1551 yin_print_snode(struct lyout *out, int level, const struct lys_node *node, int mask)
1552 {
1553 switch (node->nodetype & mask) {
1554 case LYS_CONTAINER:
1555 yin_print_container(out, level, node);
1556 break;
1557 case LYS_CHOICE:
1558 yin_print_choice(out, level, node);
1559 break;
1560 case LYS_LEAF:
1561 yin_print_leaf(out, level, node);
1562 break;
1563 case LYS_LEAFLIST:
1564 yin_print_leaflist(out, level, node);
1565 break;
1566 case LYS_LIST:
1567 yin_print_list(out, level, node);
1568 break;
1569 case LYS_USES:
1570 yin_print_uses(out, level, node);
1571 break;
1572 case LYS_GROUPING:
1573 yin_print_grouping(out, level, node);
1574 break;
1575 case LYS_ANYXML:
1576 case LYS_ANYDATA:
1577 yin_print_anydata(out, level, node);
1578 break;
1579 case LYS_CASE:
1580 yin_print_case(out, level, node);
1581 break;
1582 case LYS_RPC:
1583 case LYS_ACTION:
1584 yin_print_rpc_action(out, level, node);
1585 break;
1586 case LYS_INPUT:
1587 case LYS_OUTPUT:
1588 yin_print_input_output(out, level, node);
1589 break;
1590 case LYS_NOTIF:
1591 yin_print_notif(out, level, node);
1592 break;
1593 default:
1594 break;
1595 }
1596 }
1597
1598 static void
yin_print_revision(struct lyout * out,int level,const struct lys_module * module,const struct lys_revision * rev)1599 yin_print_revision(struct lyout *out, int level, const struct lys_module *module, const struct lys_revision *rev)
1600 {
1601 if (rev->dsc || rev->ref || rev->ext_size) {
1602 yin_print_open(out, level, NULL, "revision", "date", rev->date, 1);
1603 level++;
1604 yin_print_extension_instances(out, level, module, LYEXT_SUBSTMT_SELF, 0, rev->ext, rev->ext_size);
1605 yin_print_substmt(out, level, LYEXT_SUBSTMT_DESCRIPTION, 0, rev->dsc, module, rev->ext, rev->ext_size);
1606 yin_print_substmt(out, level, LYEXT_SUBSTMT_REFERENCE, 0, rev->ref, module, rev->ext, rev->ext_size);
1607 level--;
1608 yin_print_close(out, level, NULL, "revision", 1);
1609 } else {
1610 yin_print_open(out, level, NULL, "revision", "date", rev->date, -1);
1611 }
1612 }
1613
1614 static void
yin_print_xmlns(struct lyout * out,const struct lys_module * module)1615 yin_print_xmlns(struct lyout *out, const struct lys_module *module)
1616 {
1617 unsigned int i, lvl;
1618
1619 if (module->type) {
1620 lvl = 11;
1621 } else {
1622 lvl = 8;
1623 }
1624
1625 ly_print(out, "%*sxmlns=\"%s\"", lvl, INDENT, LY_NSYIN);
1626 if (!module->type) {
1627 ly_print(out, "\n%*sxmlns:%s=\"%s\"", lvl, INDENT, module->prefix, module->ns);
1628 } else {
1629 ly_print(out, "\n%*sxmlns:%s=\"%s\"", lvl, INDENT, module->prefix, ((struct lys_submodule*)module)->belongsto->ns);
1630 }
1631 for (i = 0; i < module->imp_size; ++i) {
1632 ly_print(out, "\n%*sxmlns:%s=\"%s\"", lvl, INDENT, module->imp[i].prefix, module->imp[i].module->ns);
1633 }
1634 }
1635
1636 static int
yin_print_model_(struct lyout * out,int level,const struct lys_module * module)1637 yin_print_model_(struct lyout *out, int level, const struct lys_module *module)
1638 {
1639 unsigned int i;
1640 int p;
1641 struct lys_node *node;
1642
1643 if (module->deviated == 1) {
1644 ly_print(out, "<!-- DEVIATED -->\n");
1645 }
1646
1647 /* (sub)module-header-stmts */
1648 if (module->type) {
1649 ly_print(out, "%*s<submodule name=\"%s\"\n", LEVEL, INDENT, module->name);
1650 yin_print_xmlns(out, module);
1651 ly_print(out, ">\n");
1652
1653 level++;
1654 if (module->version) {
1655 yin_print_substmt(out, level, LYEXT_SUBSTMT_VERSION, 0, module->version == LYS_VERSION_1_1 ? "1.1" : "1",
1656 module, module->ext, module->ext_size);
1657 }
1658 yin_print_open(out, level, NULL, "belongs-to", "module", ((struct lys_submodule *)module)->belongsto->name, 1);
1659 p = -1;
1660 while ((p = lys_ext_iter(module->ext, module->ext_size, p + 1, LYEXT_SUBSTMT_BELONGSTO)) != -1) {
1661 yin_print_extension_instances(out, level + 1, module, LYEXT_SUBSTMT_BELONGSTO, 0, &module->ext[p], 1);
1662 }
1663 yin_print_substmt(out, level + 1, LYEXT_SUBSTMT_PREFIX, 0, module->prefix,
1664 module, module->ext, module->ext_size);
1665 yin_print_close(out, level, NULL, "belongs-to", 1);
1666 } else {
1667 ly_print(out, "%*s<module name=\"%s\"\n", LEVEL, INDENT, module->name);
1668 yin_print_xmlns(out, module);
1669 ly_print(out, ">\n");
1670
1671 level++;
1672 if (module->version) {
1673 yin_print_substmt(out, level, LYEXT_SUBSTMT_VERSION, 0, module->version == LYS_VERSION_1_1 ? "1.1" : "1",
1674 module, module->ext, module->ext_size);
1675 }
1676 yin_print_substmt(out, level, LYEXT_SUBSTMT_NAMESPACE, 0, module->ns,
1677 module, module->ext, module->ext_size);
1678 yin_print_substmt(out, level, LYEXT_SUBSTMT_PREFIX, 0, module->prefix,
1679 module, module->ext, module->ext_size);
1680 }
1681
1682 /* linkage-stmts */
1683 for (i = 0; i < module->imp_size; i++) {
1684 yin_print_open(out, level, NULL, "import", "module", module->imp[i].module->name, 1);
1685 level++;
1686
1687 yin_print_extension_instances(out, level, module, LYEXT_SUBSTMT_SELF, 0,
1688 module->imp[i].ext, module->imp[i].ext_size);
1689 yin_print_substmt(out, level, LYEXT_SUBSTMT_PREFIX, 0, module->imp[i].prefix,
1690 module, module->imp[i].ext, module->imp[i].ext_size);
1691 if (module->imp[i].rev[0]) {
1692 yin_print_substmt(out, level, LYEXT_SUBSTMT_REVISIONDATE, 0, module->imp[i].rev,
1693 module, module->imp[i].ext, module->imp[i].ext_size);
1694 }
1695 yin_print_substmt(out, level, LYEXT_SUBSTMT_DESCRIPTION, 0, module->imp[i].dsc,
1696 module, module->imp[i].ext, module->imp[i].ext_size);
1697 yin_print_substmt(out, level, LYEXT_SUBSTMT_REFERENCE, 0, module->imp[i].ref,
1698 module, module->imp[i].ext, module->imp[i].ext_size);
1699
1700 level--;
1701 yin_print_close(out, level, NULL, "import", 1);
1702 }
1703 for (i = 0; i < module->inc_size; i++) {
1704 if (module->inc[i].rev[0] || module->inc[i].dsc || module->inc[i].ref || module->inc[i].ext_size) {
1705 yin_print_open(out, level, NULL, "include", "module", module->inc[i].submodule->name, 1);
1706 level++;
1707
1708 yin_print_extension_instances(out, level, module, LYEXT_SUBSTMT_SELF, 0,
1709 module->inc[i].ext, module->inc[i].ext_size);
1710 if (module->inc[i].rev[0]) {
1711 yin_print_substmt(out, level, LYEXT_SUBSTMT_REVISIONDATE, 0, module->inc[i].rev,
1712 module, module->inc[i].ext, module->inc[i].ext_size);
1713 }
1714 yin_print_substmt(out, level, LYEXT_SUBSTMT_DESCRIPTION, 0, module->inc[i].dsc,
1715 module, module->inc[i].ext, module->inc[i].ext_size);
1716 yin_print_substmt(out, level, LYEXT_SUBSTMT_REFERENCE, 0, module->inc[i].ref,
1717 module, module->inc[i].ext, module->inc[i].ext_size);
1718
1719 level--;
1720 yin_print_close(out, level, NULL, "include", 1);
1721 } else {
1722 yin_print_open(out, level, NULL, "include", "module", module->inc[i].submodule->name, -1);
1723 }
1724 }
1725
1726 /* meta-stmts */
1727 yin_print_substmt(out, level, LYEXT_SUBSTMT_ORGANIZATION, 0, module->org,
1728 module, module->ext, module->ext_size);
1729 yin_print_substmt(out, level, LYEXT_SUBSTMT_CONTACT, 0, module->contact,
1730 module, module->ext, module->ext_size);
1731 yin_print_substmt(out, level, LYEXT_SUBSTMT_DESCRIPTION, 0, module->dsc,
1732 module, module->ext, module->ext_size);
1733 yin_print_substmt(out, level, LYEXT_SUBSTMT_REFERENCE, 0, module->ref,
1734 module, module->ext, module->ext_size);
1735
1736 /* revision-stmts */
1737 for (i = 0; i < module->rev_size; i++) {
1738 yin_print_revision(out, level, module, &module->rev[i]);
1739 }
1740
1741 /* body-stmts */
1742 for (i = 0; i < module->extensions_size; ++i) {
1743 yin_print_extension(out, level, &module->extensions[i]);
1744 }
1745 if (module->ext_size) {
1746 yin_print_extension_instances(out, level, module, LYEXT_SUBSTMT_SELF, 0, module->ext, module->ext_size);
1747 }
1748
1749 for (i = 0; i < module->features_size; i++) {
1750 yin_print_feature(out, level, &module->features[i]);
1751 }
1752
1753 for (i = 0; i < module->ident_size; i++) {
1754 yin_print_identity(out, level, &module->ident[i]);
1755 }
1756
1757 for (i = 0; i < module->tpdf_size; i++) {
1758 yin_print_typedef(out, level, module, &module->tpdf[i]);
1759 }
1760
1761 LY_TREE_FOR(lys_main_module(module)->data, node) {
1762 if (node->module != module) {
1763 /* data from submodules */
1764 continue;
1765 }
1766 yin_print_snode(out, level, node, LYS_GROUPING);
1767 }
1768
1769 LY_TREE_FOR(lys_main_module(module)->data, node) {
1770 if (node->module != module) {
1771 /* data from submodules */
1772 continue;
1773 }
1774 yin_print_snode(out, level, node, LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST |
1775 LYS_USES | LYS_ANYDATA);
1776 }
1777
1778 for (i = 0; i < module->augment_size; i++) {
1779 yin_print_augment(out, level, module, &module->augment[i]);
1780 }
1781
1782 LY_TREE_FOR(lys_main_module(module)->data, node) {
1783 if (node->module != module) {
1784 /* data from submodules */
1785 continue;
1786 }
1787 yin_print_snode(out, level, node, LYS_RPC | LYS_ACTION);
1788 }
1789
1790 LY_TREE_FOR(lys_main_module(module)->data, node) {
1791 if (node->module != module) {
1792 /* data from submodules */
1793 continue;
1794 }
1795 yin_print_snode(out, level, node, LYS_NOTIF);
1796 }
1797
1798 for (i = 0; i < module->deviation_size; ++i) {
1799 yin_print_deviation(out, level, module, &module->deviation[i]);
1800 }
1801
1802 level--;
1803 if (module->type) {
1804 ly_print(out, "%*s</submodule>\n", LEVEL, INDENT);
1805 } else {
1806 ly_print(out, "%*s</module>\n", LEVEL, INDENT);
1807 }
1808 ly_print_flush(out);
1809
1810 return EXIT_SUCCESS;
1811 }
1812
1813 int
yin_print_model(struct lyout * out,const struct lys_module * module)1814 yin_print_model(struct lyout *out, const struct lys_module *module)
1815 {
1816 int level = 0;
1817
1818 ly_print(out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
1819 return yin_print_model_(out, level, module);
1820 }
1821
1822 static void
yin_print_extcomplex_bool(struct lyout * out,int level,const struct lys_module * module,struct lys_ext_instance_complex * ext,LY_STMT stmt,const char * true_val,const char * false_val,int * content)1823 yin_print_extcomplex_bool(struct lyout *out, int level, const struct lys_module *module,
1824 struct lys_ext_instance_complex *ext, LY_STMT stmt,
1825 const char *true_val, const char *false_val, int *content)
1826 {
1827 struct lyext_substmt *info;
1828 uint8_t *val;
1829
1830 val = lys_ext_complex_get_substmt(stmt, ext, &info);
1831 if (!val || !(*val)) {
1832 return;
1833 }
1834
1835 yin_print_close_parent(out, content);
1836 if (*val == 1) {
1837 yin_print_substmt(out, level, (LYEXT_SUBSTMT)stmt, 0, true_val, module, ext->ext, ext->ext_size);
1838 } else if (*val == 2) {
1839 yin_print_substmt(out, level, (LYEXT_SUBSTMT)stmt, 0, false_val, module, ext->ext, ext->ext_size);
1840 } else {
1841 LOGINT(module->ctx);
1842 }
1843 }
1844
1845 static void
yin_print_extcomplex_str(struct lyout * out,int level,const struct lys_module * module,struct lys_ext_instance_complex * ext,LY_STMT stmt,int * content)1846 yin_print_extcomplex_str(struct lyout *out, int level, const struct lys_module *module,
1847 struct lys_ext_instance_complex *ext, LY_STMT stmt, int *content)
1848 {
1849 struct lyext_substmt *info;
1850 const char **str;
1851 int c;
1852
1853 str = lys_ext_complex_get_substmt(stmt, ext, &info);
1854 if (!str || !(*str)) {
1855 return;
1856 }
1857 if (info->cardinality >= LY_STMT_CARD_SOME) {
1858 /* we have array */
1859 for (str = (const char **)(*str), c = 0; *str; str++, c++) {
1860 yin_print_close_parent(out, content);
1861 yin_print_substmt(out, level, (LYEXT_SUBSTMT)stmt, c, *str, module, ext->ext, ext->ext_size);
1862 }
1863 } else {
1864 yin_print_close_parent(out, content);
1865 yin_print_substmt(out, level, (LYEXT_SUBSTMT)stmt, 0, *str, module, ext->ext, ext->ext_size);
1866 }
1867 }
1868
1869 /* val1 is supposed to be the default value */
1870 static void
yin_print_extcomplex_flags(struct lyout * out,int level,const struct lys_module * module,struct lys_ext_instance_complex * ext,LY_STMT stmt,const char * val1_str,const char * val2_str,uint16_t val1,uint16_t val2,int * content)1871 yin_print_extcomplex_flags(struct lyout *out, int level, const struct lys_module *module,
1872 struct lys_ext_instance_complex *ext, LY_STMT stmt,
1873 const char *val1_str, const char *val2_str, uint16_t val1, uint16_t val2,
1874 int *content)
1875 {
1876 const char *str;
1877 uint16_t *flags;
1878
1879 flags = lys_ext_complex_get_substmt(stmt, ext, NULL);
1880 if (!flags) {
1881 return;
1882 }
1883
1884 if (val1 & *flags) {
1885 str = val1_str;
1886 } else if (val2 & *flags) {
1887 str = val2_str;
1888 } else if (lys_ext_iter(ext->ext, ext->ext_size, 0, (LYEXT_SUBSTMT)stmt) != -1) {
1889 /* flag not set, but since there are some extension, we are going to print the default value */
1890 str = val1_str;
1891 } else {
1892 return;
1893 }
1894
1895 yin_print_close_parent(out, content);
1896 yin_print_substmt(out, level, (LYEXT_SUBSTMT)stmt, 0, str, module, ext->ext, ext->ext_size);
1897 }
1898
1899 static void
yin_print_extension_instances(struct lyout * out,int level,const struct lys_module * module,LYEXT_SUBSTMT substmt,uint8_t substmt_index,struct lys_ext_instance ** ext,unsigned int count)1900 yin_print_extension_instances(struct lyout *out, int level, const struct lys_module *module,
1901 LYEXT_SUBSTMT substmt, uint8_t substmt_index,
1902 struct lys_ext_instance **ext, unsigned int count)
1903 {
1904 unsigned int u, x;
1905 struct lys_module *mod;
1906 const char *prefix = NULL;
1907 struct lyext_substmt *info;
1908 int content, content2, i, j, c;
1909 uint16_t *flags;
1910 const char *str;
1911 void **pp, *p;
1912 struct lys_node *siter;
1913
1914 #define YIN_PRINT_EXTCOMPLEX_SNODE(STMT) \
1915 pp = lys_ext_complex_get_substmt(STMT, (struct lys_ext_instance_complex *)ext[u], NULL); \
1916 if (!pp || !(*pp)) { break; } \
1917 LY_TREE_FOR((struct lys_node*)(*pp), siter) { \
1918 if (lys_snode2stmt(siter->nodetype) == STMT) { \
1919 yin_print_close_parent(out, &content); \
1920 yin_print_snode(out, level, siter, LYS_ANY); \
1921 } \
1922 }
1923 #define YIN_PRINT_EXTCOMPLEX_STRUCT(STMT, TYPE, FUNC) \
1924 pp = lys_ext_complex_get_substmt(STMT, (struct lys_ext_instance_complex *)ext[u], NULL); \
1925 if (!pp || !(*pp)) { break; } \
1926 if (info[i].cardinality >= LY_STMT_CARD_SOME) { /* process array */ \
1927 for (pp = *pp; *pp; pp++) { \
1928 yin_print_close_parent(out, &content); \
1929 FUNC(out, level, (TYPE *)(*pp)); \
1930 } \
1931 } else { /* single item */ \
1932 yin_print_close_parent(out, &content); \
1933 FUNC(out, level, (TYPE *)(*pp)); \
1934 }
1935 #define YIN_PRINT_EXTCOMPLEX_STRUCT_M(STMT, TYPE, FUNC, ARGS...) \
1936 pp = lys_ext_complex_get_substmt(STMT, (struct lys_ext_instance_complex *)ext[u], NULL); \
1937 if (!pp || !(*pp)) { break; } \
1938 if (info[i].cardinality >= LY_STMT_CARD_SOME) { /* process array */ \
1939 for (pp = *pp; *pp; pp++) { \
1940 yin_print_close_parent(out, &content); \
1941 FUNC(out, level, module, (TYPE *)(*pp), ##ARGS); \
1942 } \
1943 } else { /* single item */ \
1944 yin_print_close_parent(out, &content); \
1945 FUNC(out, level, module, (TYPE *)(*pp), ##ARGS); \
1946 }
1947 #define YIN_PRINT_EXTCOMPLEX_INT(STMT, TYPE, SIGN) \
1948 p = &((struct lys_ext_instance_complex*)ext[u])->content[info[i].offset]; \
1949 if (!p || !*(TYPE**)p) { break; } \
1950 if (info[i].cardinality >= LY_STMT_CARD_SOME) { /* we have array */ \
1951 for (c = 0; (*(TYPE***)p)[c]; c++) { \
1952 yin_print_close_parent(out, &content); \
1953 yin_print_##SIGN(out, level, STMT, c, module, \
1954 ext[u]->ext, ext[u]->ext_size, *(*(TYPE***)p)[c]); \
1955 } \
1956 } else { \
1957 yin_print_close_parent(out, &content); \
1958 yin_print_##SIGN(out, level, STMT, 0, module, \
1959 ext[u]->ext, ext[u]->ext_size, (**(TYPE**)p)); \
1960 }
1961
1962 for (u = 0; u < count; u++) {
1963 if (ext[u]->flags & LYEXT_OPT_INHERIT) {
1964 /* ignore the inherited extensions which were not explicitely instantiated in the module */
1965 continue;
1966 } else if (ext[u]->insubstmt != substmt || ext[u]->insubstmt_index != substmt_index) {
1967 /* do not print the other substatement than the required */
1968 continue;
1969 } else if (ext[u]->def->module == module->ctx->models.list[0] &&
1970 (!strcmp(ext[u]->arg_value, "operation") ||
1971 !strcmp(ext[u]->arg_value, "select") ||
1972 !strcmp(ext[u]->arg_value, "type"))) {
1973 /* hack for NETCONF's edit-config's operation and filter's attributes
1974 * - the annotation definition is only internal, do not print it */
1975 continue;
1976 }
1977
1978 mod = lys_main_module(ext[u]->def->module);
1979 if (mod == lys_main_module(module)) {
1980 prefix = module->prefix;
1981 } else {
1982 for (x = 0; x < module->imp_size; x++) {
1983 if (mod == module->imp[x].module) {
1984 prefix = module->imp[x].prefix;
1985 break;
1986 }
1987 }
1988 }
1989 assert(prefix);
1990
1991 content = 0;
1992 if (ext[u]->arg_value) {
1993 if (ext[u]->def->flags & LYS_YINELEM) {
1994 /* argument as element */
1995 content = 1;
1996 yin_print_open(out, level, prefix, ext[u]->def->name, NULL, NULL, content);
1997 level++;
1998 ly_print(out, "%*s<%s:%s>", LEVEL, INDENT, prefix, ext[u]->def->argument);
1999 lyxml_dump_text(out, ext[u]->arg_value, LYXML_DATA_ELEM);
2000 ly_print(out, "</%s:%s>\n", prefix, ext[u]->def->argument);
2001 level--;
2002 } else {
2003 /* argument as attribute */
2004 yin_print_open(out, level, prefix, ext[u]->def->name,
2005 ext[u]->def->argument, ext[u]->arg_value, content);
2006 }
2007 } else {
2008 yin_print_open(out, level, prefix, ext[u]->def->name, NULL, NULL, content);
2009 }
2010
2011 /* extensions */
2012 if (ext[u]->ext_size) {
2013 yin_print_close_parent(out, &content);
2014 yin_print_extension_instances(out, level + 1, module, LYEXT_SUBSTMT_SELF, 0,
2015 ext[u]->ext, ext[u]->ext_size);
2016 }
2017
2018 /* extension - type-specific part */
2019 switch (ext[u]->ext_type) {
2020 case LYEXT_FLAG:
2021 /* flag extension - nothing special */
2022 break;
2023 case LYEXT_COMPLEX:
2024 info = ((struct lys_ext_instance_complex*)ext[u])->substmt; /* shortcut */
2025 if (!info) {
2026 /* no content */
2027 break;
2028 }
2029 level++;
2030 for (i = 0; info[i].stmt; i++) {
2031 switch(info[i].stmt) {
2032 case LY_STMT_DESCRIPTION:
2033 case LY_STMT_REFERENCE:
2034 case LY_STMT_UNITS:
2035 case LY_STMT_DEFAULT:
2036 case LY_STMT_ERRTAG:
2037 case LY_STMT_ERRMSG:
2038 case LY_STMT_PREFIX:
2039 case LY_STMT_NAMESPACE:
2040 case LY_STMT_PRESENCE:
2041 case LY_STMT_REVISIONDATE:
2042 case LY_STMT_KEY:
2043 case LY_STMT_BASE:
2044 case LY_STMT_CONTACT:
2045 case LY_STMT_ORGANIZATION:
2046 case LY_STMT_PATH:
2047 yin_print_extcomplex_str(out, level, module, (struct lys_ext_instance_complex*)ext[u],
2048 info[i].stmt, &content);
2049 break;
2050 case LY_STMT_ARGUMENT:
2051 pp = lys_ext_complex_get_substmt(LY_STMT_ARGUMENT, (struct lys_ext_instance_complex*)ext[u], NULL);
2052 if (!pp || !(*pp)) {
2053 break;
2054 }
2055 yin_print_close_parent(out, &content);
2056 if (info->cardinality >= LY_STMT_CARD_SOME) {
2057 /* we have array */
2058 for (c = 0; ((const char***)pp)[0][c]; c++) {
2059 content2 = 0;
2060 yin_print_open(out, level, NULL, "argument", "name", ((const char ***)pp)[0][c], 0);
2061 j = -1;
2062 while ((j = lys_ext_iter(ext[u]->ext, ext[u]->ext_size, j + 1, LYEXT_SUBSTMT_ARGUMENT)) != -1) {
2063 if (ext[u]->ext[j]->insubstmt_index != c) {
2064 continue;
2065 }
2066 yin_print_close_parent(out, &content2);
2067 yin_print_extension_instances(out, level + 1, module, LYEXT_SUBSTMT_ARGUMENT, c,
2068 &ext[u]->ext[j], 1);
2069 }
2070 if (((uint8_t *)pp[1])[c] == 1) {
2071 yin_print_close_parent(out, &content2);
2072 yin_print_substmt(out, level + 1, LYEXT_SUBSTMT_YINELEM, c,
2073 (((uint8_t *)pp[1])[c] == 1) ? "true" : "false", module, ext[u]->ext, ext[u]->ext_size);
2074 } else {
2075 j = -1;
2076 while ((j = lys_ext_iter(ext[u]->ext, ext[u]->ext_size, j + 1, LYEXT_SUBSTMT_YINELEM)) != -1) {
2077 if (ext[u]->ext[j]->insubstmt_index == c) {
2078 yin_print_close_parent(out, &content2);
2079 yin_print_substmt(out, level + 1, LYEXT_SUBSTMT_YINELEM, c, (((uint8_t *)pp[1])[c] == 1) ? "true" : "false",
2080 module, ext[u]->ext + j, ext[u]->ext_size - j);
2081 break;
2082 }
2083 }
2084 }
2085 yin_print_close(out, level, NULL, "argument", content2);
2086 }
2087 } else {
2088 content2 = 0;
2089 yin_print_open(out, level, NULL, "argument", "name", (const char *)pp[0], 0);
2090 j = -1;
2091 while ((j = lys_ext_iter(ext[u]->ext, ext[u]->ext_size, j + 1, LYEXT_SUBSTMT_ARGUMENT)) != -1) {
2092 yin_print_close_parent(out, &content2);
2093 yin_print_extension_instances(out, level + 1, module, LYEXT_SUBSTMT_ARGUMENT, 0,
2094 &ext[u]->ext[j], 1);
2095 }
2096 if (*(uint8_t*)(pp + 1) == 1 || lys_ext_iter(ext[u]->ext, ext[u]->ext_size, 0, LYEXT_SUBSTMT_YINELEM) != -1) {
2097 yin_print_close_parent(out, &content2);
2098 yin_print_substmt(out, level + 1, LYEXT_SUBSTMT_YINELEM, 0,
2099 (*(uint8_t*)(pp + 1) == 1) ? "true" : "false", module, ext[u]->ext, ext[u]->ext_size);
2100 }
2101 yin_print_close(out, level, NULL, "argument", content2);
2102 }
2103 break;
2104 case LY_STMT_BELONGSTO:
2105 pp = lys_ext_complex_get_substmt(LY_STMT_BELONGSTO, (struct lys_ext_instance_complex*)ext[u], NULL);
2106 if (!pp || !(*pp)) {
2107 break;
2108 }
2109 if (info->cardinality >= LY_STMT_CARD_SOME) {
2110 /* we have array */
2111 for (c = 0; ((const char***)pp)[0][c]; c++) {
2112 yin_print_close_parent(out, &content);
2113 yin_print_open(out, level, NULL, "belongs-to", "module", ((const char ***)pp)[0][c], 1);
2114 j = -1;
2115 while ((j = lys_ext_iter(ext[u]->ext, ext[u]->ext_size, j + 1, LYEXT_SUBSTMT_BELONGSTO)) != -1) {
2116 yin_print_extension_instances(out, level + 1, module, LYEXT_SUBSTMT_BELONGSTO, c,
2117 &ext[u]->ext[j], 1);
2118 }
2119 yin_print_substmt(out, level + 1, LYEXT_SUBSTMT_PREFIX, c, ((const char ***)pp)[1][c],
2120 module, ext[u]->ext, ext[u]->ext_size);
2121 yin_print_close(out, level, NULL, "belongs-to", 1);
2122 }
2123 } else {
2124 yin_print_close_parent(out, &content);
2125 yin_print_open(out, level, NULL, "belongs-to", "module", (const char *)pp[0], 1);
2126 j = -1;
2127 while ((j = lys_ext_iter(ext[u]->ext, ext[u]->ext_size, j + 1, LYEXT_SUBSTMT_BELONGSTO)) != -1) {
2128 yin_print_extension_instances(out, level + 1, module, LYEXT_SUBSTMT_BELONGSTO, 0,
2129 &ext[u]->ext[j], 1);
2130 }
2131 yin_print_substmt(out, level + 1, LYEXT_SUBSTMT_PREFIX, 0, (const char *)pp[1],
2132 module, ext[u]->ext, ext[u]->ext_size);
2133 yin_print_close(out, level, NULL, "belongs-to", 1);
2134 }
2135 break;
2136 case LY_STMT_TYPE:
2137 YIN_PRINT_EXTCOMPLEX_STRUCT_M(LY_STMT_TYPE, struct lys_type, yin_print_type);
2138 break;
2139 case LY_STMT_TYPEDEF:
2140 YIN_PRINT_EXTCOMPLEX_STRUCT_M(LY_STMT_TYPEDEF, struct lys_tpdf, yin_print_typedef);
2141 break;
2142 case LY_STMT_IFFEATURE:
2143 YIN_PRINT_EXTCOMPLEX_STRUCT_M(LY_STMT_IFFEATURE, struct lys_iffeature, yin_print_iffeature);
2144 break;
2145 case LY_STMT_STATUS:
2146 flags = (uint16_t*)&((struct lys_ext_instance_complex*)ext[u])->content[info[i].offset];
2147 if (!flags || !(*flags)) {
2148 break;
2149 }
2150
2151 if (*flags & LYS_STATUS_CURR) {
2152 yin_print_close_parent(out, &content);
2153 str = "current";
2154 } else if (*flags & LYS_STATUS_DEPRC) {
2155 yin_print_close_parent(out, &content);
2156 str = "deprecated";
2157 } else if (*flags & LYS_STATUS_OBSLT) {
2158 yin_print_close_parent(out, &content);
2159 str = "obsolete";
2160 } else {
2161 /* no status flag */
2162 break;
2163 }
2164 yin_print_substmt(out, level, LYEXT_SUBSTMT_STATUS, 0, str, module, ext[u]->ext, ext[u]->ext_size);
2165 break;
2166 case LY_STMT_CONFIG:
2167 yin_print_extcomplex_flags(out, level, module, (struct lys_ext_instance_complex*)ext[u],
2168 LY_STMT_CONFIG, "true", "false",
2169 LYS_CONFIG_W | LYS_CONFIG_SET, LYS_CONFIG_R | LYS_CONFIG_SET, &content);
2170 break;
2171 case LY_STMT_MANDATORY:
2172 yin_print_extcomplex_flags(out, level, module, (struct lys_ext_instance_complex*)ext[u],
2173 LY_STMT_MANDATORY, "false", "true", LYS_MAND_FALSE, LYS_MAND_TRUE,
2174 &content);
2175 break;
2176 case LY_STMT_ORDEREDBY:
2177 yin_print_extcomplex_flags(out, level, module, (struct lys_ext_instance_complex*)ext[u],
2178 LY_STMT_ORDEREDBY, "system", "user", 0, LYS_USERORDERED, &content);
2179 break;
2180 case LY_STMT_REQINSTANCE:
2181 yin_print_extcomplex_bool(out, level, module, (struct lys_ext_instance_complex*)ext[u],
2182 info[i].stmt, "true", "false", &content);
2183 break;
2184 case LY_STMT_MODIFIER:
2185 yin_print_extcomplex_bool(out, level, module, (struct lys_ext_instance_complex*)ext[u],
2186 LY_STMT_MODIFIER, "invert-match", NULL, &content);
2187 break;
2188 case LY_STMT_DIGITS:
2189 p = &((struct lys_ext_instance_complex*)ext[u])->content[info[i].offset];
2190 if (!p) {
2191 break;
2192 }
2193 if (info->cardinality >= LY_STMT_CARD_SOME && *(uint8_t**)p) { /* we have array */
2194 for (c = 0; (*(uint8_t**)p)[c]; c++) {
2195 yin_print_close_parent(out, &content);
2196 yin_print_unsigned(out, level, LYEXT_SUBSTMT_DIGITS, c, module,
2197 ext[u]->ext, ext[u]->ext_size, (*(uint8_t**)p)[c]);
2198 }
2199 } else if ((*(uint8_t*)p)) {
2200 yin_print_close_parent(out, &content);
2201 yin_print_unsigned(out, level, LYEXT_SUBSTMT_DIGITS, 0, module,
2202 ext[u]->ext, ext[u]->ext_size, (*(uint8_t*)p));
2203 }
2204 break;
2205 case LY_STMT_MAX:
2206 YIN_PRINT_EXTCOMPLEX_INT(LYEXT_SUBSTMT_MAX, uint32_t, unsigned);
2207 break;
2208 case LY_STMT_MIN:
2209 YIN_PRINT_EXTCOMPLEX_INT(LYEXT_SUBSTMT_MIN, uint32_t, unsigned);
2210 break;
2211 case LY_STMT_POSITION:
2212 YIN_PRINT_EXTCOMPLEX_INT(LYEXT_SUBSTMT_POSITION, uint32_t, unsigned);
2213 break;
2214 case LY_STMT_VALUE:
2215 YIN_PRINT_EXTCOMPLEX_INT(LYEXT_SUBSTMT_VALUE, int32_t, signed);
2216 break;
2217 case LY_STMT_UNIQUE:
2218 pp = lys_ext_complex_get_substmt(LY_STMT_UNIQUE, (struct lys_ext_instance_complex *)ext[u], NULL);
2219 if (!pp || !(*pp)) {
2220 break;
2221 }
2222 if (info[i].cardinality >= LY_STMT_CARD_SOME) { /* process array */
2223 for (pp = *pp, c = 0; *pp; pp++, c++) {
2224 yin_print_close_parent(out, &content);
2225 yin_print_unique(out, level, module, (struct lys_unique*)(*pp));
2226 /* unique's extensions */
2227 j = -1; content2 = 0;
2228 do {
2229 j = lys_ext_iter(ext[u]->ext, ext[u]->ext_size, j + 1, LYEXT_SUBSTMT_UNIQUE);
2230 } while (j != -1 && ext[u]->ext[j]->insubstmt_index != c);
2231 if (j != -1) {
2232 yin_print_close_parent(out, &content2);
2233 do {
2234 yin_print_extension_instances(out, level + 1, module, LYEXT_SUBSTMT_UNIQUE, c, &ext[u]->ext[j], 1);
2235 do {
2236 j = lys_ext_iter(ext[u]->ext, ext[u]->ext_size, j + 1, LYEXT_SUBSTMT_UNIQUE);
2237 } while (j != -1 && ext[u]->ext[j]->insubstmt_index != c);
2238 } while (j != -1);
2239 }
2240 yin_print_close(out, level, NULL, "unique", content2);
2241 }
2242 } else { /* single item */
2243 yin_print_close_parent(out, &content);
2244 yin_print_unique(out, level, module, (struct lys_unique*)(*pp));
2245 /* unique's extensions */
2246 j = -1; content2 = 0;
2247 while ((j = lys_ext_iter(ext[u]->ext, ext[u]->ext_size, j + 1, LYEXT_SUBSTMT_UNIQUE)) != -1) {
2248 yin_print_close_parent(out, &content2);
2249 yin_print_extension_instances(out, level + 1, module, LYEXT_SUBSTMT_UNIQUE, 0, &ext[u]->ext[j], 1);
2250 }
2251 yin_print_close(out, level, NULL, "unique", content2);
2252 }
2253 break;
2254 case LY_STMT_MODULE:
2255 YIN_PRINT_EXTCOMPLEX_STRUCT(LY_STMT_MODULE, struct lys_module, yin_print_model_);
2256 break;
2257 case LY_STMT_ACTION:
2258 case LY_STMT_ANYDATA:
2259 case LY_STMT_ANYXML:
2260 case LY_STMT_CASE:
2261 case LY_STMT_CHOICE:
2262 case LY_STMT_CONTAINER:
2263 case LY_STMT_GROUPING:
2264 case LY_STMT_INPUT:
2265 case LY_STMT_OUTPUT:
2266 case LY_STMT_LEAF:
2267 case LY_STMT_LEAFLIST:
2268 case LY_STMT_LIST:
2269 case LY_STMT_NOTIFICATION:
2270 case LY_STMT_USES:
2271 YIN_PRINT_EXTCOMPLEX_SNODE(info[i].stmt);
2272 break;
2273 case LY_STMT_LENGTH:
2274 YIN_PRINT_EXTCOMPLEX_STRUCT_M(LY_STMT_LENGTH, struct lys_restr, yin_print_typerestr, "length");
2275 break;
2276 case LY_STMT_MUST:
2277 YIN_PRINT_EXTCOMPLEX_STRUCT_M(LY_STMT_MUST, struct lys_restr, yin_print_must);
2278 break;
2279 case LY_STMT_PATTERN:
2280 YIN_PRINT_EXTCOMPLEX_STRUCT_M(LY_STMT_PATTERN, struct lys_restr, yin_print_typerestr, "pattern");
2281 break;
2282 case LY_STMT_RANGE:
2283 YIN_PRINT_EXTCOMPLEX_STRUCT_M(LY_STMT_RANGE, struct lys_restr, yin_print_typerestr, "range");
2284 break;
2285 case LY_STMT_WHEN:
2286 YIN_PRINT_EXTCOMPLEX_STRUCT_M(LY_STMT_WHEN, struct lys_when, yin_print_when);
2287 break;
2288 case LY_STMT_REVISION:
2289 YIN_PRINT_EXTCOMPLEX_STRUCT_M(LY_STMT_REVISION, struct lys_revision, yin_print_revision);
2290 break;
2291 default:
2292 /* TODO */
2293 break;
2294 }
2295 }
2296 level--;
2297 break;
2298 }
2299
2300 /* close extension */
2301 yin_print_close(out, level, prefix, ext[u]->def->name, content);
2302 }
2303
2304 #undef YIN_PRINT_EXTCOMPLEX_STRUCT
2305 #undef YIN_PRINT_EXTCOMPLEX_STRUCT_M
2306 #undef YIN_PRINT_EXTCOMPLEX_INT
2307 }
2308