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, &notif->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, &notif->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