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, ¬if->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, ¬if->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