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