blob: 7592f02316c3e79eba31cf389267ca583a14c01a [file] [log] [blame]
FredGand944bdc2019-11-05 21:57:07 +08001/**
2 * @file printer_yin.c
3 * @author Fred Gan <ganshaolong@vip.qq.com>
4 * @brief YIN printer
5 *
6 * Copyright (c) 2015 - 2019 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
15#include "common.h"
16
17#include <inttypes.h>
18#include <stdint.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22
23#include "log.h"
24#include "plugins_exts.h"
25#include "printer_internal.h"
26#include "tree.h"
27#include "tree_schema.h"
28#include "tree_schema_internal.h"
29#include "plugins_types.h"
30#include "xpath.h"
31#include "xml.h"
32
33/**
34 * @brief YIN printer context.
35 */
36struct ypr_ctx {
37 struct lyout *out; /**< output specification */
38 unsigned int level; /**< current indentation level: 0 - no formatting, >= 1 indentation levels */
39 const struct lys_module *module; /**< schema to print */
40};
41
42#define LEVEL ctx->level /**< current level */
43#define INDENT (LEVEL)*2,"" /**< indentation parameters for printer functions */
44
45static void yprp_extension_instances(struct ypr_ctx *ctx, LYEXT_SUBSTMT substmt, uint8_t substmt_index,
46 struct lysp_ext_instance *ext, int *flag, unsigned int count);
47
48static void
49ypr_open(struct ypr_ctx *ctx, const char *elem_name, const char *attr_name, const char *attr_value, int flag)
50{
51 ly_print(ctx->out, "%*s<%s", INDENT, elem_name);
52
53 if (attr_name) {
54 ly_print(ctx->out, " %s=\"", attr_name);
55 lyxml_dump_text(ctx->out, attr_value, 1);
56 ly_print(ctx->out, "\"%s", flag == -1 ? "/>\n" : flag == 1 ? ">\n" : "");
57 } else if (flag) {
58 ly_print(ctx->out, flag == -1 ? "/>\n" : ">\n");
59 }
60}
61
62static void
63ypr_close(struct ypr_ctx *ctx, const char *elem_name, int flag)
64{
65 if (flag) {
66 ly_print(ctx->out, "%*s</%s>\n", INDENT, elem_name);
67 } else {
68 ly_print(ctx->out, "/>\n");
69 }
70}
71
72/*
73 * par_close_flag
74 * 0 - parent not yet closed, printing >\n, setting flag to 1
75 * 1 or NULL - parent already closed, do nothing
76 */
77static void
78ypr_close_parent(struct ypr_ctx *ctx, int *par_close_flag)
79{
80 if (par_close_flag && !(*par_close_flag)) {
81 (*par_close_flag) = 1;
82 ly_print(ctx->out, ">\n");
83 }
84}
85
86static void
87ypr_yin_arg(struct ypr_ctx *ctx, const char *arg, const char *text)
88{
89 ly_print(ctx->out, "%*s<%s>", INDENT, arg);
90 lyxml_dump_text(ctx->out, text, 0);
91 ly_print(ctx->out, "</%s>\n", arg);
92}
93
94
95
96static void
97ypr_substmt(struct ypr_ctx *ctx, LYEXT_SUBSTMT substmt, uint8_t substmt_index, const char *text, void *ext)
98{
99 unsigned int u;
100 int extflag = 0;
101
102 if (!text) {
103 /* nothing to print */
104 return;
105 }
106
107 if (ext_substmt_info[substmt].flags & SUBST_FLAG_YIN) {
108 extflag = 1;
109 ypr_open(ctx, ext_substmt_info[substmt].name, NULL, NULL, extflag);
110 } else {
111 ypr_open(ctx, ext_substmt_info[substmt].name, ext_substmt_info[substmt].arg, text, extflag);
112 }
113
114 LEVEL++;
115 LY_ARRAY_FOR(ext, u) {
116 if (((struct lysp_ext_instance*)ext)[u].insubstmt != substmt || ((struct lysp_ext_instance*)ext)[u].insubstmt_index != substmt_index) {
117 continue;
118 }
119 yprp_extension_instances(ctx, substmt, substmt_index, &((struct lysp_ext_instance*)ext)[u], &extflag, 1);
120 }
121
122 /* argument as yin-element */
123 if (ext_substmt_info[substmt].flags & SUBST_FLAG_YIN) {
124 ypr_yin_arg(ctx, ext_substmt_info[substmt].arg, text);
125 }
126
127 LEVEL--;
128 ypr_close(ctx, ext_substmt_info[substmt].name, extflag);
129}
130
131static void
132ypr_unsigned(struct ypr_ctx *ctx, LYEXT_SUBSTMT substmt, uint8_t substmt_index, void *exts, unsigned int attr_value)
133{
134 char *str;
135 if (asprintf(&str, "%u", attr_value) == -1) {
136 LOGMEM(ctx->module->ctx);
137 ctx->out->status = LY_EMEM;
138 return;
139 }
140 ypr_substmt(ctx, substmt, substmt_index, str, exts);
141 free(str);
142}
143
144static void
145ypr_signed(struct ypr_ctx *ctx, LYEXT_SUBSTMT substmt, uint8_t substmt_index, void *exts, signed int attr_value)
146{
147 char *str;
148
149 if (asprintf(&str, "%d", attr_value) == -1) {
150 LOGMEM(ctx->module->ctx);
151 ctx->out->status = LY_EMEM;
152 return;
153 }
154 ypr_substmt(ctx, substmt, substmt_index, str, exts);
155 free(str);
156}
157
158static void
159yprp_revision(struct ypr_ctx *ctx, const struct lysp_revision *rev)
160{
161 if (rev->dsc || rev->ref || rev->exts) {
162 ypr_open(ctx, "revision", "date", rev->date, 1);
163 LEVEL++;
164 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, rev->exts, NULL, 0);
165 ypr_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, rev->dsc, rev->exts);
166 ypr_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, rev->ref, rev->exts);
167 LEVEL--;
168 ypr_close(ctx, "revision", 1);
169 } else {
170 ypr_open(ctx, "revision", "date", rev->date, -1);
171 }
172}
173
174static void
175ypr_mandatory(struct ypr_ctx *ctx, uint16_t flags, void *exts, int *flag)
176{
177 if (flags & LYS_MAND_MASK) {
178 ypr_close_parent(ctx, flag);
179 ypr_substmt(ctx, LYEXT_SUBSTMT_MANDATORY, 0, (flags & LYS_MAND_TRUE) ? "true" : "false", exts);
180 }
181}
182
183static void
184ypr_config(struct ypr_ctx *ctx, uint16_t flags, void *exts, int *flag)
185{
186 if (flags & LYS_CONFIG_MASK) {
187 ypr_close_parent(ctx, flag);
188 ypr_substmt(ctx, LYEXT_SUBSTMT_CONFIG, 0, (flags & LYS_CONFIG_W) ? "true" : "false", exts);
189 }
190}
191
192static void
193ypr_status(struct ypr_ctx *ctx, uint16_t flags, void *exts, int *flag)
194{
195 const char *status = NULL;
196
197 if (flags & LYS_STATUS_CURR) {
198 ypr_close_parent(ctx, flag);
199 status = "current";
200 } else if (flags & LYS_STATUS_DEPRC) {
201 ypr_close_parent(ctx, flag);
202 status = "deprecated";
203 } else if (flags & LYS_STATUS_OBSLT) {
204 ypr_close_parent(ctx, flag);
205 status = "obsolete";
206 }
207
208 ypr_substmt(ctx, LYEXT_SUBSTMT_STATUS, 0, status, exts);
209}
210
211static void
212ypr_description(struct ypr_ctx *ctx, const char *dsc, void *exts, int *flag)
213{
214 if (dsc) {
215 ypr_close_parent(ctx, flag);
216 ypr_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, dsc, exts);
217 }
218}
219
220static void
221ypr_reference(struct ypr_ctx *ctx, const char *ref, void *exts, int *flag)
222{
223 if (ref) {
224 ypr_close_parent(ctx, flag);
225 ypr_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, ref, exts);
226 }
227}
228
229static void
230yprp_iffeatures(struct ypr_ctx *ctx, const char **iff, struct lysp_ext_instance *exts, int *flag)
231{
232 unsigned int u;
233 int extflag;
234
235 LY_ARRAY_FOR(iff, u) {
236 ypr_close_parent(ctx, flag);
237 extflag = 0;
238
239 ly_print(ctx->out, "%*s<if-feature name=\"%s", INDENT, iff[u]);
240
241 /* extensions */
242 LEVEL++;
243 LY_ARRAY_FOR(exts, u) {
244 if (exts[u].insubstmt != LYEXT_SUBSTMT_IFFEATURE || exts[u].insubstmt_index != u) {
245 continue;
246 }
247 yprp_extension_instances(ctx, LYEXT_SUBSTMT_IFFEATURE, u, &exts[u], &extflag, 1);
248 }
249 LEVEL--;
250 ly_print(ctx->out, "\"/>\n");
251 }
252}
253
254static void
255yprp_extension(struct ypr_ctx *ctx, const struct lysp_ext *ext)
256{
257 int flag = 0, flag2 = 0;
258 unsigned int i;
259
260 ypr_open(ctx, "extension", "name", ext->name, flag);
261 LEVEL++;
262
263 if (ext->exts) {
264 ypr_close_parent(ctx, &flag);
265 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, ext->exts, &flag, 0);
266 }
267
268 if (ext->argument) {
269 ypr_close_parent(ctx, &flag);
270 ypr_open(ctx, "argument", "name", ext->argument, flag2);
271
272 LEVEL++;
273 if (ext->exts) {
274 i = -1;
275 while ((i = lysp_ext_instance_iter(ext->exts, i + 1, LYEXT_SUBSTMT_ARGUMENT)) != LY_ARRAY_SIZE(ext->exts)) {
276 ypr_close_parent(ctx, &flag2);
277 yprp_extension_instances(ctx, LYEXT_SUBSTMT_ARGUMENT, 0, &ext->exts[i], &flag2, 1);
278 }
279 }
280 if ((ext->flags & LYS_YINELEM_MASK) ||
281 (ext->exts && lysp_ext_instance_iter(ext->exts, 0, LYEXT_SUBSTMT_YINELEM) != LY_ARRAY_SIZE(ext->exts))) {
282 ypr_close_parent(ctx, &flag2);
283 ypr_substmt(ctx, LYEXT_SUBSTMT_YINELEM, 0, (ext->flags & LYS_YINELEM_TRUE) ? "true" : "false", ext->exts);
284 }
285 LEVEL--;
286 ypr_close(ctx, "argument", flag2);
287 }
288
289 ypr_status(ctx, ext->flags, ext->exts, &flag);
290 ypr_description(ctx, ext->dsc, ext->exts, &flag);
291 ypr_reference(ctx, ext->ref, ext->exts, &flag);
292
293 LEVEL--;
294 ypr_close(ctx, "extension", flag);
295}
296
297static void
298yprp_feature(struct ypr_ctx *ctx, const struct lysp_feature *feat)
299{
300 int flag = 0;
301
302 ypr_open(ctx, "feature", "name", feat->name, flag);
303 LEVEL++;
304 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, feat->exts, &flag, 0);
305 yprp_iffeatures(ctx, feat->iffeatures, feat->exts, &flag);
306 ypr_status(ctx, feat->flags, feat->exts, &flag);
307 ypr_description(ctx, feat->dsc, feat->exts, &flag);
308 ypr_reference(ctx, feat->ref, feat->exts, &flag);
309 LEVEL--;
310 ypr_close(ctx, "feature", flag);
311}
312
313static void
314yprp_identity(struct ypr_ctx *ctx, const struct lysp_ident *ident)
315{
316 int flag = 0;
317 unsigned int u;
318
319 ypr_open(ctx, "identity", "name", ident->name, flag);
320 LEVEL++;
321
322 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, ident->exts, &flag, 0);
323 yprp_iffeatures(ctx, ident->iffeatures, ident->exts, &flag);
324
325 LY_ARRAY_FOR(ident->bases, u) {
326 ypr_close_parent(ctx, &flag);
327 ypr_substmt(ctx, LYEXT_SUBSTMT_BASE, u, ident->bases[u], ident->exts);
328 }
329
330 ypr_status(ctx, ident->flags, ident->exts, &flag);
331 ypr_description(ctx, ident->dsc, ident->exts, &flag);
332 ypr_reference(ctx, ident->ref, ident->exts, &flag);
333
334 LEVEL--;
335 ypr_close(ctx, "identity", flag);
336}
337
338static void
339yprp_restr(struct ypr_ctx *ctx, const struct lysp_restr *restr, const char *name, const char *attr, int *flag)
340{
341 (void)flag;
342 int inner_flag = 0;
343
344 if (!restr) {
345 return;
346 }
347
348 ly_print(ctx->out, "%*s<%s %s=\"", INDENT, name, attr);
349 lyxml_dump_text(ctx->out, (restr->arg[0] != 0x15 && restr->arg[0] != 0x06) ? restr->arg : &restr->arg[1], 1);
350 ly_print(ctx->out, "\"");
351
352 LEVEL++;
353 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, restr->exts, &inner_flag, 0);
354 if (restr->arg[0] == 0x15) {
355 ypr_close_parent(ctx, &inner_flag);
356 /* special byte value in pattern's expression: 0x15 - invert-match, 0x06 - match */
357 ypr_substmt(ctx, LYEXT_SUBSTMT_MODIFIER, 0, "invert-match", restr->exts);
358 }
359 if (restr->emsg) {
360 ypr_close_parent(ctx, &inner_flag);
361 ypr_substmt(ctx, LYEXT_SUBSTMT_ERRMSG, 0, restr->emsg, restr->exts);
362 }
363 if (restr->eapptag) {
364 ypr_close_parent(ctx, &inner_flag);
365 ypr_substmt(ctx, LYEXT_SUBSTMT_ERRTAG, 0, restr->eapptag, restr->exts);
366 }
367 ypr_description(ctx, restr->dsc, restr->exts, &inner_flag);
368 ypr_reference(ctx, restr->ref, restr->exts, &inner_flag);
369
370 LEVEL--;
371 ypr_close(ctx, name, inner_flag);
372}
373
374static void
375yprp_when(struct ypr_ctx *ctx, struct lysp_when *when, int *flag)
376{
377 int inner_flag = 0;
378 (void)flag;
379
380 if (!when) {
381 return;
382 }
383
384 ly_print(ctx->out, "%*s<when condition=\"", INDENT);
385 lyxml_dump_text(ctx->out, when->cond, 1);
386 ly_print(ctx->out, "\"");
387
388 LEVEL++;
389 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, when->exts, &inner_flag, 0);
390 ypr_description(ctx, when->dsc, when->exts, &inner_flag);
391 ypr_reference(ctx, when->ref, when->exts, &inner_flag);
392 LEVEL--;
393 ypr_close(ctx, "when", inner_flag);
394}
395
396static void
397yprp_enum(struct ypr_ctx *ctx, const struct lysp_type_enum *items, LY_DATA_TYPE type, int *flag)
398{
399 unsigned int u;
400 int inner_flag;
401 (void)flag;
402
403 LY_ARRAY_FOR(items, u) {
404 if (type == LY_TYPE_BITS) {
405 ly_print(ctx->out, "%*s<bit name=\"", INDENT);
406 lyxml_dump_text(ctx->out, items[u].name, 1);
407 ly_print(ctx->out, "\"");
408 } else { /* LY_TYPE_ENUM */
409 ly_print(ctx->out, "%*s<enum name=\"", INDENT);
410 lyxml_dump_text(ctx->out, items[u].name, 1);
411 ly_print(ctx->out, "\"");
412 }
413 inner_flag = 0;
414 LEVEL++;
415 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, items[u].exts, &inner_flag, 0);
416 yprp_iffeatures(ctx, items[u].iffeatures, items[u].exts, &inner_flag);
417 if (items[u].flags & LYS_SET_VALUE) {
418 if (type == LY_TYPE_BITS) {
419 ypr_close_parent(ctx, &inner_flag);
420 ypr_unsigned(ctx, LYEXT_SUBSTMT_POSITION, 0, items[u].exts, items[u].value);
421 } else { /* LY_TYPE_ENUM */
422 ypr_close_parent(ctx, &inner_flag);
423 ypr_signed(ctx, LYEXT_SUBSTMT_VALUE, 0, items[u].exts, items[u].value);
424 }
425 }
426 ypr_status(ctx, items[u].flags, items[u].exts, &inner_flag);
427 ypr_description(ctx, items[u].dsc, items[u].exts, &inner_flag);
428 ypr_reference(ctx, items[u].ref, items[u].exts, &inner_flag);
429 LEVEL--;
430 ypr_close(ctx, type == LY_TYPE_BITS ? "bit" : "enum", inner_flag);
431 }
432}
433
434static void
435yprp_type(struct ypr_ctx *ctx, const struct lysp_type *type)
436{
437 if (!ctx || !type) {
438 return;
439 }
440
441 unsigned int u;
442 int flag = 0;
443
444 ypr_open(ctx, "type", "name", type->name, flag);
445 LEVEL++;
446
447 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, type->exts, &flag, 0);
448
449 if (type->range || type->length || type->patterns || type->bits || type->enums) {
450 ypr_close_parent(ctx, &flag);
451 }
452 yprp_restr(ctx, type->range, "range", "value", &flag);
453 yprp_restr(ctx, type->length, "length", "value", &flag);
454 LY_ARRAY_FOR(type->patterns, u) {
455 yprp_restr(ctx, &type->patterns[u], "pattern", "value", &flag);
456 }
457 yprp_enum(ctx, type->bits, LY_TYPE_BITS, &flag);
458 yprp_enum(ctx, type->enums, LY_TYPE_ENUM, &flag);
459
460 if (type->path) {
461 ypr_close_parent(ctx, &flag);
462 ypr_substmt(ctx, LYEXT_SUBSTMT_PATH, 0, type->path, type->exts);
463 }
464 if (type->flags & LYS_SET_REQINST) {
465 ypr_close_parent(ctx, &flag);
466 ypr_substmt(ctx, LYEXT_SUBSTMT_REQINSTANCE, 0, type->require_instance ? "true" : "false", type->exts);
467 }
468 if (type->flags & LYS_SET_FRDIGITS) {
469 ypr_close_parent(ctx, &flag);
470 ypr_unsigned(ctx, LYEXT_SUBSTMT_FRACDIGITS, 0, type->exts, type->fraction_digits);
471 }
472 LY_ARRAY_FOR(type->bases, u) {
473 ypr_close_parent(ctx, &flag);
474 ypr_substmt(ctx, LYEXT_SUBSTMT_BASE, u, type->bases[u], type->exts);
475 }
476 LY_ARRAY_FOR(type->types, u) {
477 ypr_close_parent(ctx, &flag);
478 yprp_type(ctx, &type->types[u]);
479 }
480
481 LEVEL--;
482 ypr_close(ctx, "type", flag);
483}
484
485static void
486yprp_typedef(struct ypr_ctx *ctx, const struct lysp_tpdf *tpdf)
487{
488 LYOUT_CHECK(ctx->out);
489
490 ypr_open(ctx, "typedef", "name", tpdf->name, 1);
491 LEVEL++;
492
493 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, tpdf->exts, NULL, 0);
494
495 yprp_type(ctx, &tpdf->type);
496
497 if (tpdf->units) {
498 ypr_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, tpdf->units, tpdf->exts);
499 }
500 if (tpdf->dflt) {
501 ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, 0, tpdf->dflt, tpdf->exts);
502 }
503
504 ypr_status(ctx, tpdf->flags, tpdf->exts, NULL);
505 ypr_description(ctx, tpdf->dsc, tpdf->exts, NULL);
506 ypr_reference(ctx, tpdf->ref, tpdf->exts, NULL);
507
508 LEVEL--;
509 ypr_close(ctx, "typedef", 1);
510}
511
512static void yprp_node(struct ypr_ctx *ctx, const struct lysp_node *node);
513static void yprp_action(struct ypr_ctx *ctx, const struct lysp_action *action);
514
515static void
516yprp_grouping(struct ypr_ctx *ctx, const struct lysp_grp *grp)
517{
518 unsigned int u;
519 int flag = 0;
520 struct lysp_node *data;
521
522 LYOUT_CHECK(ctx->out);
523
524 ypr_open(ctx, "grouping", "name", grp->name, flag);
525 LEVEL++;
526
527 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, grp->exts, &flag, 0);
528 ypr_status(ctx, grp->flags, grp->exts, &flag);
529 ypr_description(ctx, grp->dsc, grp->exts, &flag);
530 ypr_reference(ctx, grp->ref, grp->exts, &flag);
531
532 LY_ARRAY_FOR(grp->typedefs, u) {
533 ypr_close_parent(ctx, &flag);
534 yprp_typedef(ctx, &grp->typedefs[u]);
535 }
536
537 LY_ARRAY_FOR(grp->groupings, u) {
538 ypr_close_parent(ctx, &flag);
539 yprp_grouping(ctx, &grp->groupings[u]);
540 }
541
542 LY_LIST_FOR(grp->data, data) {
543 ypr_close_parent(ctx, &flag);
544 yprp_node(ctx, data);
545 }
546
547 LY_ARRAY_FOR(grp->actions, u) {
548 ypr_close_parent(ctx, &flag);
549 yprp_action(ctx, &grp->actions[u]);
550 }
551
552 LEVEL--;
553 ypr_close(ctx, "grouping", flag);
554}
555
556static void
557yprp_inout(struct ypr_ctx *ctx, const struct lysp_action_inout *inout, int *flag)
558{
559 unsigned int u;
560 struct lysp_node *data;
561
562 if (!inout->nodetype) {
563 /* nodetype not set -> input/output is empty */
564 return;
565 }
566 ypr_close_parent(ctx, flag);
567
568 ypr_open(ctx, (inout->nodetype == LYS_INPUT ? "input" : "output"), NULL, NULL, *flag);
569 LEVEL++;
570
571 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, inout->exts, NULL, 0);
572 LY_ARRAY_FOR(inout->musts, u) {
573 yprp_restr(ctx, &inout->musts[u], "must", "condition", NULL);
574 }
575 LY_ARRAY_FOR(inout->typedefs, u) {
576 yprp_typedef(ctx, &inout->typedefs[u]);
577 }
578 LY_ARRAY_FOR(inout->groupings, u) {
579 yprp_grouping(ctx, &inout->groupings[u]);
580 }
581
582 LY_LIST_FOR(inout->data, data) {
583 yprp_node(ctx, data);
584 }
585
586 LEVEL--;
587 ypr_close(ctx, (inout->nodetype == LYS_INPUT ? "input" : "output"), 1);
588}
589
590static void
591yprp_notification(struct ypr_ctx *ctx, const struct lysp_notif *notif)
592{
593 unsigned int u;
594 int flag = 0;
595 struct lysp_node *data;
596
597 LYOUT_CHECK(ctx->out);
598
599 ypr_open(ctx, "notification", "name", notif->name, flag);
600
601 LEVEL++;
602 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, notif->exts, &flag, 0);
603 yprp_iffeatures(ctx, notif->iffeatures, notif->exts, &flag);
604
605 LY_ARRAY_FOR(notif->musts, u) {
606 ypr_close_parent(ctx, &flag);
607 yprp_restr(ctx, &notif->musts[u], "must", "condition", &flag);
608 }
609 ypr_status(ctx, notif->flags, notif->exts, &flag);
610 ypr_description(ctx, notif->dsc, notif->exts, &flag);
611 ypr_reference(ctx, notif->ref, notif->exts, &flag);
612
613 LY_ARRAY_FOR(notif->typedefs, u) {
614 ypr_close_parent(ctx, &flag);
615 yprp_typedef(ctx, &notif->typedefs[u]);
616 }
617
618 LY_ARRAY_FOR(notif->groupings, u) {
619 ypr_close_parent(ctx, &flag);
620 yprp_grouping(ctx, &notif->groupings[u]);
621 }
622
623 LY_LIST_FOR(notif->data, data) {
624 ypr_close_parent(ctx, &flag);
625 yprp_node(ctx, data);
626 }
627
628 LEVEL--;
629 ypr_close(ctx, "notification", flag);
630}
631
632static void
633yprp_action(struct ypr_ctx *ctx, const struct lysp_action *action)
634{
635 unsigned int u;
636 int flag = 0;
637
638 LYOUT_CHECK(ctx->out);
639
640 ypr_open(ctx, action->parent ? "action" : "rpc", "name", action->name, flag);
641
642 LEVEL++;
643 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, action->exts, &flag, 0);
644 yprp_iffeatures(ctx, action->iffeatures, action->exts, &flag);
645 ypr_status(ctx, action->flags, action->exts, &flag);
646 ypr_description(ctx, action->dsc, action->exts, &flag);
647 ypr_reference(ctx, action->ref, action->exts, &flag);
648
649 LY_ARRAY_FOR(action->typedefs, u) {
650 ypr_close_parent(ctx, &flag);
651 yprp_typedef(ctx, &action->typedefs[u]);
652 }
653
654 LY_ARRAY_FOR(action->groupings, u) {
655 ypr_close_parent(ctx, &flag);
656 yprp_grouping(ctx, &action->groupings[u]);
657 }
658
659 yprp_inout(ctx, &action->input, &flag);
660 yprp_inout(ctx, &action->output, &flag);
661
662 LEVEL--;
663 ypr_close(ctx, action->parent ? "action" : "rpc", flag);
664}
665
666static void
667yprp_node_common1(struct ypr_ctx *ctx, const struct lysp_node *node, int *flag)
668{
669 ypr_open(ctx, lys_nodetype2str(node->nodetype), "name", node->name, *flag);
670 LEVEL++;
671
672 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, node->exts, flag, 0);
673 yprp_when(ctx, node->when, flag);
674 yprp_iffeatures(ctx, node->iffeatures, node->exts, flag);
675}
676
677static void
678yprp_node_common2(struct ypr_ctx *ctx, const struct lysp_node *node, int *flag)
679{
680 ypr_config(ctx, node->flags, node->exts, flag);
681 if (node->nodetype & (LYS_CHOICE | LYS_LEAF | LYS_ANYDATA)) {
682 ypr_mandatory(ctx, node->flags, node->exts, flag);
683 }
684 ypr_status(ctx, node->flags, node->exts, flag);
685 ypr_description(ctx, node->dsc, node->exts, flag);
686 ypr_reference(ctx, node->ref, node->exts, flag);
687}
688
689static void
690yprp_container(struct ypr_ctx *ctx, const struct lysp_node *node)
691{
692 unsigned int u;
693 int flag = 0;
694 struct lysp_node *child;
695 struct lysp_node_container *cont = (struct lysp_node_container *)node;
696
697 yprp_node_common1(ctx, node, &flag);
698
699 LY_ARRAY_FOR(cont->musts, u) {
700 ypr_close_parent(ctx, &flag);
701 yprp_restr(ctx, &cont->musts[u], "must", "condition", &flag);
702 }
703 if (cont->presence) {
704 ypr_close_parent(ctx, &flag);
705 ypr_substmt(ctx, LYEXT_SUBSTMT_PRESENCE, 0, cont->presence, cont->exts);
706 }
707
708 yprp_node_common2(ctx, node, &flag);
709
710 LY_ARRAY_FOR(cont->typedefs, u) {
711 ypr_close_parent(ctx, &flag);
712 yprp_typedef(ctx, &cont->typedefs[u]);
713 }
714
715 LY_ARRAY_FOR(cont->groupings, u) {
716 ypr_close_parent(ctx, &flag);
717 yprp_grouping(ctx, &cont->groupings[u]);
718 }
719
720 LY_LIST_FOR(cont->child, child) {
721 ypr_close_parent(ctx, &flag);
722 yprp_node(ctx, child);
723 }
724
725 LY_ARRAY_FOR(cont->actions, u) {
726 ypr_close_parent(ctx, &flag);
727 yprp_action(ctx, &cont->actions[u]);
728 }
729
730 LY_ARRAY_FOR(cont->notifs, u) {
731 ypr_close_parent(ctx, &flag);
732 yprp_notification(ctx, &cont->notifs[u]);
733 }
734
735 LEVEL--;
736 ypr_close(ctx, "container", flag);
737}
738
739static void
740yprp_case(struct ypr_ctx *ctx, const struct lysp_node *node)
741{
742 int flag = 0;
743 struct lysp_node *child;
744 struct lysp_node_case *cas = (struct lysp_node_case *)node;
745
746 yprp_node_common1(ctx, node, &flag);
747 yprp_node_common2(ctx, node, &flag);
748
749 LY_LIST_FOR(cas->child, child) {
750 ypr_close_parent(ctx, &flag);
751 yprp_node(ctx, child);
752 }
753
754 LEVEL--;
755 ypr_close(ctx, "case", flag);
756}
757
758static void
759yprp_choice(struct ypr_ctx *ctx, const struct lysp_node *node)
760{
761 int flag = 0;
762 struct lysp_node *child;
763 struct lysp_node_choice *choice = (struct lysp_node_choice *)node;
764
765 yprp_node_common1(ctx, node, &flag);
766
767 if (choice->dflt) {
768 ypr_close_parent(ctx, &flag);
769 ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, 0, choice->dflt, choice->exts);
770 }
771
772 yprp_node_common2(ctx, node, &flag);
773
774 LY_LIST_FOR(choice->child, child) {
775 ypr_close_parent(ctx, &flag);
776 yprp_node(ctx, child);
777 }
778
779 LEVEL--;
780 ypr_close(ctx, "choice", flag);
781}
782
783static void
784yprp_leaf(struct ypr_ctx *ctx, const struct lysp_node *node)
785{
786 unsigned int u;
787 struct lysp_node_leaf *leaf = (struct lysp_node_leaf *)node;
788
789 int flag = 1;
790 yprp_node_common1(ctx, node, &flag);
791
792 yprp_type(ctx, &leaf->type);
793 ypr_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, leaf->units, leaf->exts);
794 LY_ARRAY_FOR(leaf->musts, u) {
795 yprp_restr(ctx, &leaf->musts[u], "must", "condition", &flag);
796 }
797 ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, 0, leaf->dflt, leaf->exts);
798
799 yprp_node_common2(ctx, node, &flag);
800
801 LEVEL--;
802 ypr_close(ctx, "leaf", flag);
803}
804
805static void
806yprp_leaflist(struct ypr_ctx *ctx, const struct lysp_node *node)
807{
808 unsigned int u;
809 struct lysp_node_leaflist *llist = (struct lysp_node_leaflist *)node;
810 int flag = 1;
811
812 yprp_node_common1(ctx, node, &flag);
813
814 yprp_type(ctx, &llist->type);
815 ypr_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, llist->units, llist->exts);
816 LY_ARRAY_FOR(llist->musts, u) {
817 yprp_restr(ctx, &llist->musts[u], "must", "condition", NULL);
818 }
819 LY_ARRAY_FOR(llist->dflts, u) {
820 ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, u, llist->dflts[u], llist->exts);
821 }
822
823 ypr_config(ctx, node->flags, node->exts, NULL);
824
825 if (llist->flags & LYS_SET_MIN) {
826 ypr_unsigned(ctx, LYEXT_SUBSTMT_MIN, 0, llist->exts, llist->min);
827 }
828 if (llist->flags & LYS_SET_MAX) {
829 if (llist->max) {
830 ypr_unsigned(ctx, LYEXT_SUBSTMT_MAX, 0, llist->exts, llist->max);
831 } else {
832 ypr_substmt(ctx, LYEXT_SUBSTMT_MAX, 0, "unbounded", llist->exts);
833 }
834 }
835
836 if (llist->flags & LYS_ORDBY_MASK) {
837 ypr_substmt(ctx, LYEXT_SUBSTMT_ORDEREDBY, 0, (llist->flags & LYS_ORDBY_USER) ? "user" : "system", llist->exts);
838 }
839
840 ypr_status(ctx, node->flags, node->exts, &flag);
841 ypr_description(ctx, node->dsc, node->exts, &flag);
842 ypr_reference(ctx, node->ref, node->exts, &flag);
843
844 LEVEL--;
845 ypr_close(ctx, "leaf-list", flag);
846}
847
848static void
849yprp_list(struct ypr_ctx *ctx, const struct lysp_node *node)
850{
851 unsigned int u;
852 int flag = 0;
853 struct lysp_node *child;
854 struct lysp_node_list *list = (struct lysp_node_list *)node;
855
856 yprp_node_common1(ctx, node, &flag);
857
858 LY_ARRAY_FOR(list->musts, u) {
859 ypr_close_parent(ctx, &flag);
860 yprp_restr(ctx, &list->musts[u], "must", "condition", &flag);
861 }
862 if (list->key) {
863 ypr_close_parent(ctx, &flag);
864 ypr_substmt(ctx, LYEXT_SUBSTMT_KEY, 0, list->key, list->exts);
865 }
866 LY_ARRAY_FOR(list->uniques, u) {
867 ypr_close_parent(ctx, &flag);
868 ypr_substmt(ctx, LYEXT_SUBSTMT_UNIQUE, u, list->uniques[u], list->exts);
869 }
870
871 ypr_config(ctx, node->flags, node->exts, NULL);
872
873 if (list->flags & LYS_SET_MIN) {
874 ypr_unsigned(ctx, LYEXT_SUBSTMT_MIN, 0, list->exts, list->min);
875 }
876 if (list->flags & LYS_SET_MAX) {
877 if (list->max) {
878 ypr_unsigned(ctx, LYEXT_SUBSTMT_MAX, 0, list->exts, list->max);
879 } else {
880 ypr_substmt(ctx, LYEXT_SUBSTMT_MAX, 0, "unbounded", list->exts);
881 }
882 }
883
884 if (list->flags & LYS_ORDBY_MASK) {
885 ypr_close_parent(ctx, &flag);
886 ypr_substmt(ctx, LYEXT_SUBSTMT_ORDEREDBY, 0, (list->flags & LYS_ORDBY_USER) ? "user" : "system", list->exts);
887 }
888
889 ypr_status(ctx, node->flags, node->exts, &flag);
890 ypr_description(ctx, node->dsc, node->exts, &flag);
891 ypr_reference(ctx, node->ref, node->exts, &flag);
892
893 LY_ARRAY_FOR(list->typedefs, u) {
894 ypr_close_parent(ctx, &flag);
895 yprp_typedef(ctx, &list->typedefs[u]);
896 }
897
898 LY_ARRAY_FOR(list->groupings, u) {
899 ypr_close_parent(ctx, &flag);
900 yprp_grouping(ctx, &list->groupings[u]);
901 }
902
903 LY_LIST_FOR(list->child, child) {
904 ypr_close_parent(ctx, &flag);
905 yprp_node(ctx, child);
906 }
907
908 LY_ARRAY_FOR(list->actions, u) {
909 ypr_close_parent(ctx, &flag);
910 yprp_action(ctx, &list->actions[u]);
911 }
912
913 LY_ARRAY_FOR(list->notifs, u) {
914 ypr_close_parent(ctx, &flag);
915 yprp_notification(ctx, &list->notifs[u]);
916 }
917
918 LEVEL--;
919 ypr_close(ctx, "list", flag);
920}
921
922static void
923yprp_refine(struct ypr_ctx *ctx, struct lysp_refine *refine)
924{
925 unsigned int u;
926 int flag = 0;
927
928 ypr_open(ctx, "refine", "target-node", refine->nodeid, flag);
929 LEVEL++;
930
931 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, refine->exts, &flag, 0);
932 yprp_iffeatures(ctx, refine->iffeatures, refine->exts, &flag);
933
934 LY_ARRAY_FOR(refine->musts, u) {
935 ypr_close_parent(ctx, &flag);
936 yprp_restr(ctx, &refine->musts[u], "must", "condition", &flag);
937 }
938
939 if (refine->presence) {
940 ypr_close_parent(ctx, &flag);
941 ypr_substmt(ctx, LYEXT_SUBSTMT_PRESENCE, 0, refine->presence, refine->exts);
942 }
943
944 LY_ARRAY_FOR(refine->dflts, u) {
945 ypr_close_parent(ctx, &flag);
946 ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, u, refine->dflts[u], refine->exts);
947 }
948
949 ypr_config(ctx, refine->flags, refine->exts, &flag);
950 ypr_mandatory(ctx, refine->flags, refine->exts, &flag);
951
952 if (refine->flags & LYS_SET_MIN) {
953 ypr_close_parent(ctx, &flag);
954 ypr_unsigned(ctx, LYEXT_SUBSTMT_MIN, 0, refine->exts, refine->min);
955 }
956 if (refine->flags & LYS_SET_MAX) {
957 ypr_close_parent(ctx, &flag);
958 if (refine->max) {
959 ypr_unsigned(ctx, LYEXT_SUBSTMT_MAX, 0, refine->exts, refine->max);
960 } else {
961 ypr_substmt(ctx, LYEXT_SUBSTMT_MAX, 0, "unbounded", refine->exts);
962 }
963 }
964
965 ypr_description(ctx, refine->dsc, refine->exts, &flag);
966 ypr_reference(ctx, refine->ref, refine->exts, &flag);
967
968 LEVEL--;
969 ypr_close(ctx, "refine", flag);
970}
971
972static void
973yprp_augment(struct ypr_ctx *ctx, const struct lysp_augment *aug)
974{
975 unsigned int u;
976 struct lysp_node *child;
977
978 ypr_open(ctx, "augment", "target-node", aug->nodeid, 1);
979 LEVEL++;
980
981 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, aug->exts, NULL, 0);
982 yprp_when(ctx, aug->when, NULL);
983 yprp_iffeatures(ctx, aug->iffeatures, aug->exts, NULL);
984 ypr_status(ctx, aug->flags, aug->exts, NULL);
985 ypr_description(ctx, aug->dsc, aug->exts, NULL);
986 ypr_reference(ctx, aug->ref, aug->exts, NULL);
987
988 LY_LIST_FOR(aug->child, child) {
989 yprp_node(ctx, child);
990 }
991
992 LY_ARRAY_FOR(aug->actions, u) {
993 yprp_action(ctx, &aug->actions[u]);
994 }
995
996 LY_ARRAY_FOR(aug->notifs, u) {
997 yprp_notification(ctx, &aug->notifs[u]);
998 }
999
1000 LEVEL--;
1001 ypr_close(ctx, "augment", 1);
1002}
1003
1004
1005static void
1006yprp_uses(struct ypr_ctx *ctx, const struct lysp_node *node)
1007{
1008 unsigned int u;
1009 int flag = 0;
1010 struct lysp_node_uses *uses = (struct lysp_node_uses *)node;
1011
1012 yprp_node_common1(ctx, node, &flag);
1013 yprp_node_common2(ctx, node, &flag);
1014
1015 LY_ARRAY_FOR(uses->refines, u) {
1016 ypr_close_parent(ctx, &flag);
1017 yprp_refine(ctx, &uses->refines[u]);
1018 }
1019
1020 LY_ARRAY_FOR(uses->augments, u) {
1021 ypr_close_parent(ctx, &flag);
1022 yprp_augment(ctx, &uses->augments[u]);
1023 }
1024
1025 LEVEL--;
1026 ypr_close(ctx, "uses", flag);
1027}
1028
1029static void
1030yprp_anydata(struct ypr_ctx *ctx, const struct lysp_node *node)
1031{
1032 unsigned int u;
1033 int flag = 0;
1034 struct lysp_node_anydata *any = (struct lysp_node_anydata *)node;
1035
1036 yprp_node_common1(ctx, node, &flag);
1037
1038 LY_ARRAY_FOR(any->musts, u) {
1039 ypr_close_parent(ctx, &flag);
1040 yprp_restr(ctx, &any->musts[u], "must", "condition", &flag);
1041 }
1042
1043 yprp_node_common2(ctx, node, &flag);
1044
1045 LEVEL--;
1046 ypr_close(ctx, lys_nodetype2str(node->nodetype), flag);
1047}
1048
1049static void
1050yprp_node(struct ypr_ctx *ctx, const struct lysp_node *node)
1051{
1052 LYOUT_CHECK(ctx->out);
1053
1054 switch (node->nodetype) {
1055 case LYS_CONTAINER:
1056 yprp_container(ctx, node);
1057 break;
1058 case LYS_CHOICE:
1059 yprp_choice(ctx, node);
1060 break;
1061 case LYS_LEAF:
1062 yprp_leaf(ctx, node);
1063 break;
1064 case LYS_LEAFLIST:
1065 yprp_leaflist(ctx, node);
1066 break;
1067 case LYS_LIST:
1068 yprp_list(ctx, node);
1069 break;
1070 case LYS_USES:
1071 yprp_uses(ctx, node);
1072 break;
1073 case LYS_ANYXML:
1074 case LYS_ANYDATA:
1075 yprp_anydata(ctx, node);
1076 break;
1077 case LYS_CASE:
1078 yprp_case(ctx, node);
1079 break;
1080 default:
1081 break;
1082 }
1083}
1084
1085static void
1086yprp_deviation(struct ypr_ctx *ctx, const struct lysp_deviation *deviation)
1087{
1088 unsigned int v;
1089 struct lysp_deviate_add *add;
1090 struct lysp_deviate_rpl *rpl;
1091 struct lysp_deviate_del *del;
1092 struct lysp_deviate *elem;
1093
1094 ypr_open(ctx, "deviation", "target-node", deviation->nodeid, 1);
1095 LEVEL++;
1096
1097 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, deviation->exts, NULL, 0);
1098 ypr_description(ctx, deviation->dsc, deviation->exts, NULL);
1099 ypr_reference(ctx, deviation->ref, deviation->exts, NULL);
1100
1101 LY_LIST_FOR(deviation->deviates, elem) {
1102 ly_print(ctx->out, "%*s<deviate value=\"", INDENT);
1103 if (elem->mod == LYS_DEV_NOT_SUPPORTED) {
1104 if (elem->exts) {
1105 ly_print(ctx->out, "not-supported\"/>\n");
1106 LEVEL++;
1107
1108 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, elem->exts, NULL, 0);
1109 } else {
1110 ly_print(ctx->out, "not-supported\"/>\n");
1111 continue;
1112 }
1113 } else if (elem->mod == LYS_DEV_ADD) {
1114 add = (struct lysp_deviate_add*)elem;
1115 ly_print(ctx->out, "add\">\n");
1116 LEVEL++;
1117
1118 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, add->exts, NULL, 0);
1119 ypr_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, add->units, add->exts);
1120 LY_ARRAY_FOR(add->musts, v) {
1121 yprp_restr(ctx, &add->musts[v], "must", "condition", NULL);
1122 }
1123 LY_ARRAY_FOR(add->uniques, v) {
1124 ypr_substmt(ctx, LYEXT_SUBSTMT_UNIQUE, v, add->uniques[v], add->exts);
1125 }
1126 LY_ARRAY_FOR(add->dflts, v) {
1127 ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, v, add->dflts[v], add->exts);
1128 }
1129 ypr_config(ctx, add->flags, add->exts, NULL);
1130 ypr_mandatory(ctx, add->flags, add->exts, NULL);
1131 if (add->flags & LYS_SET_MIN) {
1132 ypr_unsigned(ctx, LYEXT_SUBSTMT_MIN, 0, add->exts, add->min);
1133 }
1134 if (add->flags & LYS_SET_MAX) {
1135 if (add->max) {
1136 ypr_unsigned(ctx, LYEXT_SUBSTMT_MAX, 0, add->exts, add->max);
1137 } else {
1138 ypr_substmt(ctx, LYEXT_SUBSTMT_MAX, 0, "unbounded", add->exts);
1139 }
1140 }
1141 } else if (elem->mod == LYS_DEV_REPLACE) {
1142 rpl = (struct lysp_deviate_rpl*)elem;
1143 ly_print(ctx->out, "replace\">\n");
1144 LEVEL++;
1145
1146 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, rpl->exts, NULL, 0);
1147 if (rpl->type) {
1148 yprp_type(ctx, rpl->type);
1149 }
1150 ypr_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, rpl->units, rpl->exts);
1151 ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, 0, rpl->dflt, rpl->exts);
1152 ypr_config(ctx, rpl->flags, rpl->exts, NULL);
1153 ypr_mandatory(ctx, rpl->flags, rpl->exts, NULL);
1154 if (rpl->flags & LYS_SET_MIN) {
1155 ypr_unsigned(ctx, LYEXT_SUBSTMT_MIN, 0, rpl->exts, rpl->min);
1156 }
1157 if (rpl->flags & LYS_SET_MAX) {
1158 if (rpl->max) {
1159 ypr_unsigned(ctx, LYEXT_SUBSTMT_MAX, 0, rpl->exts, rpl->max);
1160 } else {
1161 ypr_substmt(ctx, LYEXT_SUBSTMT_MAX, 0, "unbounded", rpl->exts);
1162 }
1163 }
1164 } else if (elem->mod == LYS_DEV_DELETE) {
1165 del = (struct lysp_deviate_del*)elem;
1166 ly_print(ctx->out, "delete\">\n");
1167 LEVEL++;
1168
1169 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, del->exts, NULL, 0);
1170 ypr_substmt(ctx, LYEXT_SUBSTMT_UNITS, 0, del->units, del->exts);
1171 LY_ARRAY_FOR(del->musts, v) {
1172 yprp_restr(ctx, &del->musts[v], "must", "condition", NULL);
1173 }
1174 LY_ARRAY_FOR(del->uniques, v) {
1175 ypr_substmt(ctx, LYEXT_SUBSTMT_UNIQUE, v, del->uniques[v], del->exts);
1176 }
1177 LY_ARRAY_FOR(del->dflts, v) {
1178 ypr_substmt(ctx, LYEXT_SUBSTMT_DEFAULT, v, del->dflts[v], del->exts);
1179 }
1180 }
1181
1182 LEVEL--;
1183 ypr_close(ctx, "deviate", 1);
1184 }
1185
1186 LEVEL--;
1187 ypr_close(ctx, "deviation", 1);
1188}
1189
1190/**
1191 * @brief Minimal print of a schema.
1192 *
1193 * To print parsed schema when the parsed form was already removed
1194 */
1195static LY_ERR
1196ypr_missing_format(struct ypr_ctx *ctx, const struct lys_module *module)
1197{
1198 /* module-header-stmts */
1199 if (module->version) {
1200 if (module->version) {
1201 ypr_substmt(ctx, LYEXT_SUBSTMT_VERSION, 0, module->version == LYS_VERSION_1_1 ? "1.1" : "1", NULL);
1202 }
1203 }
1204 ypr_substmt(ctx, LYEXT_SUBSTMT_NAMESPACE, 0, module->ns, NULL);
1205 ypr_substmt(ctx, LYEXT_SUBSTMT_PREFIX, 0, module->prefix, NULL);
1206
1207 /* meta-stmts */
1208 if (module->org || module->contact || module->dsc || module->ref) {
1209 ly_print(ctx->out, "\n");
1210 }
1211 ypr_substmt(ctx, LYEXT_SUBSTMT_ORGANIZATION, 0, module->org, NULL);
1212 ypr_substmt(ctx, LYEXT_SUBSTMT_CONTACT, 0, module->contact, NULL);
1213 ypr_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, module->dsc, NULL);
1214 ypr_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, module->ref, NULL);
1215
1216 /* revision-stmts */
1217 if (module->revision) {
1218 ypr_open(ctx, "revision", "date", module->revision, -1);
1219 }
1220
1221 LEVEL--;
1222 ypr_close(ctx, "module", 1);
1223 ly_print_flush(ctx->out);
1224
1225 return LY_SUCCESS;
1226}
1227
1228static void
1229ypr_xmlns(struct ypr_ctx *ctx, const struct lys_module *module, unsigned int indent)
1230{
1231 unsigned int u;
1232
1233 ly_print(ctx->out, "%*sxmlns=\"%s\"", indent + INDENT, YIN_NS_URI);
1234 ly_print(ctx->out, "\n%*sxmlns:%s=\"%s\"", indent + INDENT, module->prefix, module->ns);
1235
1236 struct lysp_module *modp = module->parsed;
1237
1238 LY_ARRAY_FOR(modp->imports, u){
1239 ly_print(ctx->out, "\n%*sxmlns:%s=\"%s\"", indent + INDENT, modp->imports[u].prefix, modp->imports[u].module->ns);
1240 }
1241}
1242
1243struct ext_substmt_info_s stmt_attr_info[] = {
1244 {NULL, NULL, 0}, /**< LY_STMT_NONE*/
1245 {"status", "value", SUBST_FLAG_ID}, /**< LY_STMT_STATUS */
1246 {"config", "value", SUBST_FLAG_ID}, /**< LY_STMT_CONFIG */
1247 {"mandatory", "value", SUBST_FLAG_ID}, /**< LY_STMT_MANDATORY */
1248 {"units", "name", SUBST_FLAG_ID}, /**< LY_STMT_UNITS */
1249 {"default", "value", SUBST_FLAG_ID}, /**< LY_STMT_DEFAULT */
1250 {"type", "name", SUBST_FLAG_ID}, /**< LY_STMT_TYPE */
1251 {"action", "name", SUBST_FLAG_ID}, /**< LY_STMT_ACTION */
1252 {"anydata", "name", SUBST_FLAG_ID}, /**< LY_STMT_ANYDATA */
1253 {"anyxml", "name", SUBST_FLAG_ID}, /**< LY_STMT_ANYXML */
1254 {"argument", "name", SUBST_FLAG_ID}, /**< LY_STMT_ARGUMENT */
1255 {"augment", "target-node", SUBST_FLAG_ID}, /**< LY_STMT_AUGMENT */
1256 {"base", "name", SUBST_FLAG_ID}, /**< LY_STMT_BASE */
1257 {"belongs-to", "module", SUBST_FLAG_ID}, /**< LY_STMT_BELONGS_TO */
1258 {"bit", "name", SUBST_FLAG_ID}, /**< LY_STMT_BIT */
1259 {"case", "name", SUBST_FLAG_ID}, /**< LY_STMT_CASE */
1260 {"choice", "name", SUBST_FLAG_ID}, /**< LY_STMT_CHOICE */
1261 {"contact", "text", SUBST_FLAG_YIN},/**< LY_STMT_CONTACT */
1262 {"container", "name", SUBST_FLAG_ID}, /**< LY_STMT_CONTAINER */
1263 {"description", "text", SUBST_FLAG_YIN},/**< LY_STMT_DESCRIPTION */
1264 {"deviate", "value", SUBST_FLAG_ID}, /**< LY_STMT_DEVIATE */
1265 {"deviation", "target-node", SUBST_FLAG_ID}, /**< LY_STMT_DEVIATION */
1266 {"enum", "name", SUBST_FLAG_ID}, /**< LY_STMT_ENUM */
1267 {"error-app-tag", "value", SUBST_FLAG_ID}, /**< LY_STMT_ERROR_APP_TAG */
1268 {"error-message", "value", SUBST_FLAG_YIN},/**< LY_STMT_ERROR_MESSAGE */
1269 {"extension", "name", SUBST_FLAG_ID}, /**< LY_STMT_EXTENSION */
1270 {"feature", "name", SUBST_FLAG_ID}, /**< LY_STMT_FEATURE */
1271 {"fraction-digits", "value", SUBST_FLAG_ID}, /**< LY_STMT_FRACTION_DIGITS */
1272 {"grouping", "name", SUBST_FLAG_ID}, /**< LY_STMT_GROUPING */
1273 {"identity", "name", SUBST_FLAG_ID}, /**< LY_STMT_IDENTITY */
1274 {"if-feature", "name", SUBST_FLAG_ID}, /**< LY_STMT_IF_FEATURE */
1275 {"import", "module", SUBST_FLAG_ID}, /**< LY_STMT_IMPORT */
1276 {"include", "module", SUBST_FLAG_ID}, /**< LY_STMT_INCLUDE */
1277 {"input", NULL, 0}, /**< LY_STMT_INPUT */
1278 {"key", "value", SUBST_FLAG_ID}, /**< LY_STMT_KEY */
1279 {"leaf", "name", SUBST_FLAG_ID}, /**< LY_STMT_LEAF */
1280 {"leaf-list", "name", SUBST_FLAG_ID}, /**< LY_STMT_LEAF_LIST */
1281 {"length", "value", SUBST_FLAG_ID}, /**< LY_STMT_LENGTH */
1282 {"list", "name", SUBST_FLAG_ID}, /**< LY_STMT_LIST */
1283 {"max-elements", "value", SUBST_FLAG_ID}, /**< LY_STMT_MAX_ELEMENTS */
1284 {"min-elements", "value", SUBST_FLAG_ID}, /**< LY_STMT_MIN_ELEMENTS */
1285 {"modifier", "value", SUBST_FLAG_ID}, /**< LY_STMT_MODIFIER */
1286 {"module", "name", SUBST_FLAG_ID}, /**< LY_STMT_MODULE */
1287 {"must", "condition", SUBST_FLAG_ID}, /**< LY_STMT_MUST */
1288 {"namespace", "uri", SUBST_FLAG_ID}, /**< LY_STMT_NAMESPACE */
1289 {"notification", "name", SUBST_FLAG_ID}, /**< LY_STMT_NOTIFICATION */
1290 {"ordered-by", "value", SUBST_FLAG_ID}, /**< LY_STMT_ORDERED_BY */
1291 {"organization", "text", SUBST_FLAG_YIN},/**< LY_STMT_ORGANIZATION */
1292 {"output", NULL, 0}, /**< LY_STMT_OUTPUT */
1293 {"path", "value", SUBST_FLAG_ID}, /**< LY_STMT_PATH */
1294 {"pattern", "value", SUBST_FLAG_ID}, /**< LY_STMT_PATTERN */
1295 {"position", "value", SUBST_FLAG_ID}, /**< LY_STMT_POSITION */
1296 {"prefix", "value", SUBST_FLAG_ID}, /**< LY_STMT_PREFIX */
1297 {"presence", "value", SUBST_FLAG_ID}, /**< LY_STMT_PRESENCE */
1298 {"range", "value", SUBST_FLAG_ID}, /**< LY_STMT_RANGE */
1299 {"reference", "text", SUBST_FLAG_YIN},/**< LY_STMT_REFERENCE */
1300 {"refine", "target-node", SUBST_FLAG_ID}, /**< LY_STMT_REFINE */
1301 {"require-instance", "value", SUBST_FLAG_ID}, /**< LY_STMT_REQUIRE_INSTANCE */
1302 {"revision", "date", SUBST_FLAG_ID}, /**< LY_STMT_REVISION */
1303 {"revision-date", "date", SUBST_FLAG_ID}, /**< LY_STMT_REVISION_DATE */
1304 {"rpc", "name", SUBST_FLAG_ID}, /**< LY_STMT_RPC */
1305 {"submodule", "name", SUBST_FLAG_ID}, /**< LY_STMT_SUBMODULE */
1306 {"typedef", "name", SUBST_FLAG_ID}, /**< LY_STMT_TYPEDEF */
1307 {"unique", "tag", SUBST_FLAG_ID}, /**< LY_STMT_UNIQUE */
1308 {"uses", "name", SUBST_FLAG_ID}, /**< LY_STMT_USES */
1309 {"value", "value", SUBST_FLAG_ID}, /**< LY_STMT_VALUE */
1310 {"when", "condition", SUBST_FLAG_ID}, /**< LY_STMT_WHEN */
1311 {"yang-version", "value", SUBST_FLAG_ID}, /**< LY_STMT_YANG_VERSION */
1312 {"yin-element", "value", SUBST_FLAG_ID}, /**< LY_STMT_YIN_ELEMENT */
1313 {NULL, NULL, 0}, /**< LY_STMT_EXTENSION_INSTANCE */
1314 {NULL, NULL, 0}, /**< LY_STMT_SYNTAX_SEMICOLON */
1315 {NULL, NULL, 0}, /**< LY_STMT_SYNTAX_LEFT_BRACE */
1316 {NULL, NULL, 0}, /**< LY_STMT_SYNTAX_RIGHT_BRACE */
1317 {NULL, NULL, 0}, /**< LY_STMT_ARG_TEXT */
1318 {NULL, NULL, 0}, /**< LY_STMT_ARG_VALUE */
1319};
1320
1321static void
1322yprp_stmt(struct ypr_ctx *ctx, struct lysp_stmt *stmt)
1323{
1324 struct lysp_stmt *childstmt;
1325 int flag = stmt->child ? 1 : -1;
1326
1327 /* TODO:
1328 the extension instance substatements in extension instances (LY_STMT_EXTENSION_INSTANCE)
1329 cannot find the compiled information, so it is needed to be done,
1330 currently it is ignored */
1331 if(stmt_attr_info[stmt->kw].name) {
1332 if(stmt_attr_info[stmt->kw].flags & SUBST_FLAG_YIN) {
1333 ypr_open(ctx, stmt->stmt, NULL, NULL, flag);
1334 ypr_yin_arg(ctx, stmt_attr_info[stmt->kw].arg, stmt->arg);
1335 }
1336 else {
1337 ypr_open(ctx, stmt->stmt, stmt_attr_info[stmt->kw].arg, stmt->arg, flag);
1338 }
1339 }
1340
1341 if (stmt->child) {
1342 LEVEL++;
1343 LY_LIST_FOR(stmt->child, childstmt) {
1344 yprp_stmt(ctx, childstmt);
1345 }
1346 LEVEL--;
1347 ypr_close(ctx, stmt->stmt, flag);
1348 }
1349}
1350
1351/**
1352 * @param[in] count Number of extensions to print, 0 to print them all.
1353 */
1354static void
1355yprp_extension_instances(struct ypr_ctx *ctx, LYEXT_SUBSTMT substmt, uint8_t substmt_index,
1356 struct lysp_ext_instance *ext, int *flag, unsigned int count)
1357{
1358 unsigned int u;
1359 char *str;
1360 struct lysp_stmt *stmt;
1361 const char *argument;
1362 const char *ext_argument;
1363
1364 if (!count && ext) {
1365 count = LY_ARRAY_SIZE(ext);
1366 }
1367 LY_ARRAY_FOR(ext, u) {
1368 if (!count) {
1369 break;
1370 }
1371
1372 count--;
1373 if (ext->insubstmt != substmt || ext->insubstmt_index != substmt_index) {
1374 continue;
1375 }
1376
1377 if (!ext->compiled && ext->yin) {
1378 ly_print(ctx->out, "%*s<%s/> <!-- Model comes from different input format, extensions must be resolved first. -->\n", INDENT, ext[u].name);
1379 continue;
1380 }
1381
1382 ypr_close_parent(ctx, flag);
1383 int inner_flag = 0;
1384 argument = NULL;
1385 ext_argument = NULL;
1386
1387 if (ext[u].compiled) {
1388 argument = ext[u].compiled->argument;
1389 ext_argument = ext[u].compiled->def->argument;
1390 } else {
1391 argument = ext[u].argument;
1392 }
1393
1394 if (ext->yin) {
1395 ypr_open(ctx, ext[u].name, NULL, NULL, 1);
1396 if (asprintf(&str, "%s:%s", ext[u].compiled->def->module->prefix, ext_argument) == -1) {
1397 LOGMEM(ctx->module->ctx);
1398 ctx->out->status = LY_EMEM;
1399 return;
1400 }
1401 LEVEL++;
1402 inner_flag = 1;
1403 ypr_yin_arg(ctx, str, argument);
1404 free(str);
1405 str = NULL;
1406 LEVEL--;
1407 } else {
1408 ypr_open(ctx, ext[u].name, ext_argument, argument, inner_flag);
1409 }
1410
1411 LEVEL++;
1412 LY_LIST_FOR(ext[u].child, stmt) {
1413 ypr_close_parent(ctx, &inner_flag);
1414 yprp_stmt(ctx, stmt);
1415 }
1416 LEVEL--;
1417 ypr_close(ctx, ext[u].name, inner_flag);
1418 }
1419}
1420
1421LY_ERR
1422yin_print_parsed(struct lyout *out, const struct lys_module *module)
1423{
1424 unsigned int u;
1425 struct lysp_node *data;
1426 struct lysp_module *modp = module->parsed;
1427 struct ypr_ctx ctx_ = {.out = out, .level = 0, .module = module}, *ctx = &ctx_;
1428
1429 ly_print(ctx->out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
1430 ly_print(ctx->out, "%*s<module name=\"%s\"\n", INDENT, module->name);
1431 ypr_xmlns(ctx, module, 8);
1432 ly_print(ctx->out, ">\n");
1433
1434 LEVEL++;
1435
1436 if (!modp) {
1437 ly_print(ctx->out, "%*s<!-- PARSED INFORMATION ARE NOT FULLY PRESENT -->\n", INDENT);
1438 return ypr_missing_format(ctx, module);
1439 }
1440
1441 /* module-header-stmts */
1442 if (module->version) {
1443 if (module->version) {
1444 ypr_substmt(ctx, LYEXT_SUBSTMT_VERSION, 0, module->version == LYS_VERSION_1_1 ? "1.1" : "1", modp->exts);
1445 }
1446 }
1447 ypr_substmt(ctx, LYEXT_SUBSTMT_NAMESPACE, 0, module->ns, modp->exts);
1448 ypr_substmt(ctx, LYEXT_SUBSTMT_PREFIX, 0, module->prefix, modp->exts);
1449
1450 /* linkage-stmts */
1451 LY_ARRAY_FOR(modp->imports, u) {
1452 ypr_open(ctx, "import", "module", modp->imports[u].module->name, 1);
1453 LEVEL++;
1454 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, modp->imports[u].exts, NULL, 0);
1455 ypr_substmt(ctx, LYEXT_SUBSTMT_PREFIX, 0, modp->imports[u].prefix, modp->imports[u].exts);
1456 if (modp->imports[u].rev[0]) {
1457 ypr_substmt(ctx, LYEXT_SUBSTMT_REVISIONDATE, 0, modp->imports[u].rev, modp->imports[u].exts);
1458 }
1459 ypr_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, modp->imports[u].dsc, modp->imports[u].exts);
1460 ypr_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, modp->imports[u].ref, modp->imports[u].exts);
1461 LEVEL--;
1462 ypr_close(ctx, "import", 1);
1463 }
1464 LY_ARRAY_FOR(modp->includes, u) {
1465 if (modp->includes[u].rev[0] || modp->includes[u].dsc || modp->includes[u].ref || modp->includes[u].exts) {
1466 ypr_open(ctx, "include", "module", modp->includes[u].submodule->name, 1);
1467 LEVEL++;
1468 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, modp->includes[u].exts, NULL, 0);
1469 if (modp->includes[u].rev[0]) {
1470 ypr_substmt(ctx, LYEXT_SUBSTMT_REVISIONDATE, 0, modp->includes[u].rev, modp->includes[u].exts);
1471 }
1472 ypr_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, modp->includes[u].dsc, modp->includes[u].exts);
1473 ypr_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, modp->includes[u].ref, modp->includes[u].exts);
1474 LEVEL--;
1475 ly_print(out, "%*s}\n", INDENT);
1476 } else {
1477 ypr_open(ctx, "include", "module", modp->includes[u].submodule->name, -1);
1478 }
1479 }
1480
1481 /* meta-stmts */
1482 if (module->org || module->contact || module->dsc || module->ref) {
1483 ly_print(out, "\n");
1484 }
1485 ypr_substmt(ctx, LYEXT_SUBSTMT_ORGANIZATION, 0, module->org, modp->exts);
1486 ypr_substmt(ctx, LYEXT_SUBSTMT_CONTACT, 0, module->contact, modp->exts);
1487 ypr_substmt(ctx, LYEXT_SUBSTMT_DESCRIPTION, 0, module->dsc, modp->exts);
1488 ypr_substmt(ctx, LYEXT_SUBSTMT_REFERENCE, 0, module->ref, modp->exts);
1489
1490 /* revision-stmts */
1491 if (modp->revs) {
1492 ly_print(out, "\n");
1493 }
1494 LY_ARRAY_FOR(modp->revs, u) {
1495 yprp_revision(ctx, &modp->revs[u]);
1496 }
1497 /* body-stmts */
1498 LY_ARRAY_FOR(modp->extensions, u) {
1499 ly_print(out, "\n");
1500 yprp_extension(ctx, &modp->extensions[u]);
1501 }
1502 if (modp->exts) {
1503 ly_print(out, "\n");
1504 yprp_extension_instances(ctx, LYEXT_SUBSTMT_SELF, 0, module->parsed->exts, NULL, 0);
1505 }
1506
1507 LY_ARRAY_FOR(modp->features, u) {
1508 yprp_feature(ctx, &modp->features[u]);
1509 }
1510
1511 LY_ARRAY_FOR(modp->identities, u) {
1512 yprp_identity(ctx, &modp->identities[u]);
1513 }
1514
1515 LY_ARRAY_FOR(modp->typedefs, u) {
1516 yprp_typedef(ctx, &modp->typedefs[u]);
1517 }
1518
1519 LY_ARRAY_FOR(modp->groupings, u) {
1520 yprp_grouping(ctx, &modp->groupings[u]);
1521 }
1522
1523 LY_LIST_FOR(modp->data, data) {
1524 yprp_node(ctx, data);
1525 }
1526
1527 LY_ARRAY_FOR(modp->augments, u) {
1528 yprp_augment(ctx, &modp->augments[u]);
1529 }
1530
1531 LY_ARRAY_FOR(modp->rpcs, u) {
1532 yprp_action(ctx, &modp->rpcs[u]);
1533 }
1534
1535 LY_ARRAY_FOR(modp->notifs, u) {
1536 yprp_notification(ctx, &modp->notifs[u]);
1537 }
1538
1539 LY_ARRAY_FOR(modp->deviations, u) {
1540 yprp_deviation(ctx, &modp->deviations[u]);
1541 }
1542
1543 LEVEL--;
1544 ly_print(out, "%*s</module>\n", INDENT);
1545 ly_print_flush(out);
1546
1547 return LY_SUCCESS;
1548}
1549