1 /**
2  * @file printer/info.c
3  * @author Michal Vasko <mvasko@cesnet.cz>
4  * @brief INFO 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 
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <assert.h>
19 
20 #include "common.h"
21 #include "printer.h"
22 #include "tree_schema.h"
23 #include "resolve.h"
24 
25 #define INDENT_LEN 11
26 
27 static void
info_print_text(struct lyout * out,const char * text,const char * label)28 info_print_text(struct lyout *out, const char *text, const char *label)
29 {
30     const char *ptr1, *ptr2;
31     int first = 1;
32 
33     ly_print(out, "%-*s", INDENT_LEN, label);
34 
35     if (text) {
36         ptr1 = text;
37         while (1) {
38             ptr2 = strchr(ptr1, '\n');
39             if (!ptr2) {
40                 if (first) {
41                     ly_print(out, "%s\n", ptr1);
42                     first = 0;
43                 } else {
44                     ly_print(out, "%*s%s\n", INDENT_LEN, "", ptr1);
45                 }
46                 break;
47             }
48             ++ptr2;
49             if (first) {
50                 ly_print(out, "%.*s", (int)(ptr2-ptr1), ptr1);
51                 first = 0;
52             } else {
53                 ly_print(out, "%*s%.*s", INDENT_LEN, "", (int)(ptr2-ptr1), ptr1);
54             }
55             ptr1 = ptr2;
56         }
57     }
58 
59     if (first) {
60         ly_print(out, "\n");
61     }
62 }
63 
64 static void
info_print_snode(struct lyout * out,const struct lys_node * parent,const struct lys_node * node,const char * label)65 info_print_snode(struct lyout *out, const struct lys_node *parent, const struct lys_node *node, const char *label)
66 {
67     assert(strlen(label) < INDENT_LEN-1);
68 
69     ly_print(out, "%-*s", INDENT_LEN, label);
70 
71     if (node) {
72         if (node->name) {
73             ly_print(out, "%s \"", strnodetype(node->nodetype));
74             if (parent != lys_parent(node)) {
75                 ly_print(out, "%s:", node->module->prefix);
76             }
77             ly_print(out, "%s\"\n", node->name);
78         } else {
79             ly_print(out, "%s\n", (node->nodetype == LYS_INPUT ? "input" : "output"));
80         }
81         node = node->next;
82         for (; node; node = node->next) {
83             if (node->name) {
84                 ly_print(out, "%*s%s \"", INDENT_LEN, "", strnodetype(node->nodetype));
85                 if (parent != lys_parent(node)) {
86                     ly_print(out, "%s:", node->module->prefix);
87                 }
88                 ly_print(out, "%s\"\n", node->name);
89             } else {
90                 ly_print(out, "%*s%s\n", INDENT_LEN, "", (node->nodetype == LYS_INPUT ? "input" : "output"));
91             }
92         }
93     } else {
94         ly_print(out, "\n");
95     }
96 }
97 
98 static void
info_print_flags(struct lyout * out,uint16_t flags,uint16_t mask,int is_list)99 info_print_flags(struct lyout *out, uint16_t flags, uint16_t mask, int is_list)
100 {
101     if (mask & LYS_CONFIG_MASK) {
102         ly_print(out, "%-*s", INDENT_LEN, "Config: ");
103         if (flags & LYS_CONFIG_R) {
104             ly_print(out, "read-only\n");
105         } else {
106             ly_print(out, "read-write\n");
107         }
108     }
109 
110     if (mask & LYS_STATUS_MASK) {
111         ly_print(out, "%-*s", INDENT_LEN, "Status: ");
112 
113         if (flags & LYS_STATUS_DEPRC) {
114             ly_print(out, "deprecated\n");
115         } else if (flags & LYS_STATUS_OBSLT) {
116             ly_print(out, "obsolete\n");
117         } else {
118             ly_print(out, "current\n");
119         }
120     }
121 
122     if (mask & LYS_MAND_MASK) {
123         ly_print(out, "%-*s", INDENT_LEN, "Mandatory: ");
124 
125         if (flags & LYS_MAND_TRUE) {
126             ly_print(out, "yes\n");
127         } else {
128             ly_print(out, "no\n");
129         }
130     }
131 
132     if (is_list && (mask & LYS_USERORDERED)) {
133         ly_print(out, "%-*s", INDENT_LEN, "Order: ");
134 
135         if (flags & LYS_USERORDERED) {
136             ly_print(out, "user-ordered\n");
137         } else {
138             ly_print(out, "system-ordered\n");
139         }
140     }
141 
142     if (!is_list && (mask & LYS_FENABLED)) {
143         ly_print(out, "%-*s", INDENT_LEN, "Enabled: ");
144 
145         if (flags & LYS_FENABLED) {
146             ly_print(out, "yes\n");
147         } else {
148             ly_print(out, "no\n");
149         }
150     }
151 }
152 
153 static void
info_print_if_feature(struct lyout * out,const struct lys_module * module,struct lys_iffeature * iffeature,uint8_t iffeature_size)154 info_print_if_feature(struct lyout *out, const struct lys_module *module,
155                       struct lys_iffeature *iffeature, uint8_t iffeature_size)
156 {
157     int i;
158 
159     ly_print(out, "%-*s", INDENT_LEN, "If-feats: ");
160 
161     if (iffeature_size) {
162         ly_print_iffeature(out, module, &iffeature[0], 1);
163         ly_print(out, "\n");
164         for (i = 1; i < iffeature_size; ++i) {
165             ly_print(out, "%*s", INDENT_LEN, "");
166             ly_print_iffeature(out, module, &iffeature[i], 1);
167             ly_print(out, "\n");
168         }
169     } else {
170         ly_print(out, "\n");
171     }
172 }
173 
174 static void
info_print_when(struct lyout * out,const struct lys_when * when)175 info_print_when(struct lyout *out, const struct lys_when *when)
176 {
177     ly_print(out, "%-*s", INDENT_LEN, "When: ");
178     if (when) {
179         ly_print(out, "%s\n", when->cond);
180     } else {
181         ly_print(out, "\n");
182     }
183 }
184 
185 static void
info_print_must(struct lyout * out,const struct lys_restr * must,uint8_t must_size)186 info_print_must(struct lyout *out, const struct lys_restr *must, uint8_t must_size)
187 {
188     int i;
189 
190     ly_print(out, "%-*s", INDENT_LEN, "Must: ");
191 
192     if (must_size) {
193         ly_print(out, "%s\n", must[0].expr);
194         for (i = 1; i < must_size; ++i) {
195             ly_print(out, "%*s%s\n", INDENT_LEN, "", must[i].expr);
196         }
197     } else {
198         ly_print(out, "\n");
199     }
200 }
201 
202 static void
info_print_typedef(struct lyout * out,const struct lys_tpdf * tpdf,uint8_t tpdf_size)203 info_print_typedef(struct lyout *out, const struct lys_tpdf *tpdf, uint8_t tpdf_size)
204 {
205     int i;
206 
207     ly_print(out, "%-*s", INDENT_LEN, "Typedefs: ");
208 
209     if (tpdf_size) {
210         ly_print(out, "%s\n", tpdf[0].name);
211         for (i = 1; i < tpdf_size; ++i) {
212             ly_print(out, "%*s%s", INDENT_LEN, "", tpdf[i].name);
213         }
214     } else {
215         ly_print(out, "\n");
216     }
217 }
218 
219 static void
info_print_typedef_with_include(struct lyout * out,const struct lys_module * mod)220 info_print_typedef_with_include(struct lyout *out, const struct lys_module *mod)
221 {
222     int i, j, first = 1;
223 
224     ly_print(out, "%-*s", INDENT_LEN, "Typedefs: ");
225 
226     if (mod->tpdf_size) {
227         ly_print(out, "%s\n", mod->tpdf[0].name);
228         first = 0;
229 
230         for (i = 1; i < mod->tpdf_size; ++i) {
231             ly_print(out, "%*s%s\n", INDENT_LEN, "", mod->tpdf[i].name);
232         }
233     }
234 
235     for (i = 0; i < mod->inc_size; ++i) {
236         if (mod->inc[i].submodule->tpdf_size) {
237             if (first) {
238                 ly_print(out, "%s (%s)\n", mod->inc[i].submodule->tpdf[0].name, mod->inc[i].submodule->name);
239                 j = 1;
240             } else {
241                 j = 0;
242             }
243             first = 0;
244 
245             for (; j < mod->inc[i].submodule->tpdf_size; ++j) {
246                 ly_print(out, "%*s%s (%s)\n", INDENT_LEN, "", mod->inc[i].submodule->tpdf[j].name, mod->inc[i].submodule->name);
247             }
248         }
249     }
250 
251     if (first) {
252         ly_print(out, "\n");
253     }
254 }
255 
256 static void
info_print_type_detail_(struct lyout * out,const struct lys_type * type,int uni)257 info_print_type_detail_(struct lyout *out, const struct lys_type *type, int uni)
258 {
259     unsigned int i;
260     struct lys_type *orig;
261 
262     if (uni) {
263         ly_print(out, "  ");
264     }
265 
266     switch (type->base) {
267     case LY_TYPE_BINARY:
268         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "binary");
269         if (!uni) {
270             info_print_text(out, (type->info.binary.length ? type->info.binary.length->expr : NULL), "Length: ");
271         }
272         break;
273     case LY_TYPE_BITS:
274         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "bits");
275 
276         assert(type->info.bits.count);
277         if (!uni) {
278             ly_print(out, "%-*s%u %s\n", INDENT_LEN, "Bits: ", type->info.bits.bit[0].pos, type->info.bits.bit[0].name);
279             for (i = 1; i < type->info.bits.count; ++i) {
280                 ly_print(out, "%*s%u %s\n", INDENT_LEN, "", type->info.bits.bit[i].pos, type->info.bits.bit[i].name);
281             }
282         }
283 
284         break;
285     case LY_TYPE_BOOL:
286         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "boolean");
287         break;
288     case LY_TYPE_DEC64:
289         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "decimal64");
290         if (!uni) {
291             info_print_text(out, (type->info.dec64.range ? type->info.dec64.range->expr : NULL), "Range: ");
292             assert(type->info.dec64.dig);
293             ly_print(out, "%-*s%u%s\n", INDENT_LEN, "Frac dig: ", type->info.dec64.dig,
294                      type->der->type.der ? " (derived)" : "");
295         }
296         break;
297     case LY_TYPE_EMPTY:
298         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "empty");
299         break;
300     case LY_TYPE_ENUM:
301         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "enumeration");
302 
303         for (orig = (struct lys_type *)type; !orig->info.enums.count; orig = &orig->der->type);
304 
305         if (!uni) {
306             ly_print(out, "%-*s%s (%d)\n", INDENT_LEN, "Values: ",
307                      orig->info.enums.enm[0].name, orig->info.enums.enm[0].value);
308             for (i = 1; i < orig->info.enums.count; ++i) {
309                 ly_print(out, "%*s%s (%d)\n", INDENT_LEN, "",
310                          orig->info.enums.enm[i].name, orig->info.enums.enm[i].value);
311             }
312         }
313 
314         break;
315     case LY_TYPE_IDENT:
316         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "identityref");
317         if (!uni && type->info.ident.count) {
318             ly_print(out, "%-*s%s\n", INDENT_LEN, "Idents:   ", type->info.ident.ref[0]->name);
319             for (i = 1; i < type->info.ident.count; ++i) {
320                 ly_print(out, "%*s%s\n", INDENT_LEN, "", type->info.ident.ref[i]->name);
321             }
322         }
323         break;
324     case LY_TYPE_INST:
325         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "instance-identifier");
326         if (!uni) {
327             ly_print(out, "%-*s%s\n", INDENT_LEN, "Required: ", (type->info.inst.req < 1 ? "no" : "yes"));
328         }
329         break;
330     case LY_TYPE_INT8:
331         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "int8");
332         goto int_range;
333     case LY_TYPE_INT16:
334         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "int16");
335         goto int_range;
336     case LY_TYPE_INT32:
337         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "int32");
338         goto int_range;
339     case LY_TYPE_INT64:
340         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "int64");
341         goto int_range;
342     case LY_TYPE_UINT8:
343         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "uint8");
344         goto int_range;
345     case LY_TYPE_UINT16:
346         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "uint16");
347         goto int_range;
348     case LY_TYPE_UINT32:
349         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "uint32");
350         goto int_range;
351     case LY_TYPE_UINT64:
352         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "uint64");
353 
354 int_range:
355         if (!uni) {
356             info_print_text(out, (type->info.num.range ? type->info.num.range->expr : NULL), "Range: ");
357         }
358         break;
359     case LY_TYPE_LEAFREF:
360         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "leafref");
361         if (!uni) {
362             info_print_text(out, type->info.lref.path, "Path: ");
363         }
364         break;
365     case LY_TYPE_STRING:
366         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "string");
367         if (!uni) {
368             info_print_text(out, (type->info.str.length ? type->info.str.length->expr : NULL), "Length: ");
369 
370             ly_print(out, "%-*s", INDENT_LEN, "Pattern: ");
371             if (type->info.str.pat_count) {
372                 ly_print(out, "%s%s\n", &type->info.str.patterns[0].expr[1],
373                          type->info.str.patterns[0].expr[0] == 0x15 ? " (invert-match)" : "");
374                 for (i = 1; i < type->info.str.pat_count; ++i) {
375                     ly_print(out, "%*s%s%s\n", INDENT_LEN, "", &type->info.str.patterns[i].expr[1],
376                              type->info.str.patterns[i].expr[0] == 0x15 ? " (invert-match)" : "");
377                 }
378             } else {
379                 ly_print(out, "\n");
380             }
381         }
382 
383         break;
384     case LY_TYPE_UNION:
385         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "union");
386 
387         if (!uni) {
388             for (i = 0; i < type->info.uni.count; ++i) {
389                 info_print_type_detail_(out, &type->info.uni.types[i], 1);
390             }
391         }
392         break;
393     default:
394         /* unused outside libyang, we never should be here */
395         LOGINT(type->parent->module->ctx);
396         ly_print(out, "%-*s%s\n", INDENT_LEN, "Base type: ", "UNKNOWN");
397         break;
398     }
399 
400     if (uni) {
401         ly_print(out, "  ");
402     }
403     ly_print(out, "%-*s", INDENT_LEN, "Superior: ");
404     if (type->der) {
405         if (!lys_type_is_local(type)) {
406             ly_print(out, "%s:", type->der->module->name);
407         }
408         ly_print(out, "%s\n", type->der->name);
409     } else {
410         ly_print(out, "\n");
411     }
412 }
413 
414 static void
info_print_type_detail(struct lyout * out,const struct lys_type * type,int * UNUSED (first))415 info_print_type_detail(struct lyout *out, const struct lys_type *type, int * UNUSED(first))
416 {
417     return info_print_type_detail_(out, type, 0);
418 }
419 
420 static void
info_print_list_constr(struct lyout * out,uint32_t min,uint32_t max)421 info_print_list_constr(struct lyout *out, uint32_t min, uint32_t max)
422 {
423     ly_print(out, "%-*s%u..", INDENT_LEN, "Elements: ", min);
424     if (max) {
425         ly_print(out, "%u\n", max);
426     } else {
427         ly_print(out, "unbounded\n");
428     }
429 }
430 
431 static void
info_print_unique(struct lyout * out,const struct lys_unique * unique,uint8_t unique_size)432 info_print_unique(struct lyout *out, const struct lys_unique *unique, uint8_t unique_size)
433 {
434     int i, j;
435 
436     ly_print(out, "%-*s", INDENT_LEN, "Unique: ");
437 
438     if (unique_size) {
439         ly_print(out, "%s\n", unique[0].expr[0]);
440         for (i = 0; i < unique_size; ++i) {
441             for (j = (!i ? 1 : 0); j < unique[i].expr_size; ++j) {
442                 ly_print(out, "%*s%s\n", INDENT_LEN, "", unique[i].expr[j]);
443             }
444         }
445     } else {
446         ly_print(out, "\n");
447     }
448 }
449 
450 static void
info_print_revision(struct lyout * out,const struct lys_revision * rev,uint8_t rev_size)451 info_print_revision(struct lyout *out, const struct lys_revision *rev, uint8_t rev_size)
452 {
453     int i;
454 
455     ly_print(out, "%-*s", INDENT_LEN, "Revisions: ");
456 
457     if (rev_size) {
458         ly_print(out, "%s\n", rev[0].date);
459         for (i = 1; i < rev_size; ++i) {
460             ly_print(out, "%*s%s\n", INDENT_LEN, "", rev[i].date);
461         }
462     } else {
463         ly_print(out, "\n");
464     }
465 }
466 
467 static void
info_print_import_with_include(struct lyout * out,const struct lys_module * mod)468 info_print_import_with_include(struct lyout *out, const struct lys_module *mod)
469 {
470     int first = 1, i, j;
471 
472     ly_print(out, "%-*s", INDENT_LEN, "Imports: ");
473     if (mod->imp_size) {
474         ly_print(out, "%s:%s\n", mod->imp[0].prefix, mod->imp[0].module->name);
475         i = 1;
476         first = 0;
477 
478         for (; i < mod->imp_size; ++i) {
479             ly_print(out, "%*s%s:%s\n", INDENT_LEN, "", mod->imp[i].prefix, mod->imp[i].module->name);
480         }
481     }
482 
483     for (j = 0; j < mod->inc_size; ++j) {
484         if (mod->inc[j].submodule->imp_size) {
485             if (first) {
486                 ly_print(out, "%s:%s (%s)\n",
487                         mod->inc[j].submodule->imp[0].prefix, mod->inc[j].submodule->imp[0].module->name, mod->inc[j].submodule->name);
488                 i = 1;
489             } else {
490                 i = 0;
491             }
492             first = 0;
493 
494             for (; i < mod->inc[j].submodule->imp_size; ++i) {
495                 ly_print(out, "%*s%s:%s (%s)\n", INDENT_LEN, "",
496                         mod->inc[j].submodule->imp[i].prefix, mod->inc[j].submodule->imp[i].module->name, mod->inc[j].submodule->name);
497             }
498         }
499     }
500 
501     if (first) {
502         ly_print(out, "\n");
503     }
504 }
505 
506 static void
info_print_include(struct lyout * out,const struct lys_module * mod)507 info_print_include(struct lyout *out, const struct lys_module *mod)
508 {
509     int first = 1, i;
510 
511     ly_print(out, "%-*s", INDENT_LEN, "Includes: ");
512     if (mod->inc_size) {
513         ly_print(out, "%s\n", mod->inc[0].submodule->name);
514         i = 1;
515         first = 0;
516 
517         for (; i < mod->inc_size; ++i) {
518             ly_print(out, "%*s%s\n", INDENT_LEN, "", mod->inc[i].submodule->name);
519         }
520     }
521 
522     if (first) {
523         ly_print(out, "\n");
524     }
525 }
526 
527 static void
info_print_augment(struct lyout * out,const struct lys_module * mod)528 info_print_augment(struct lyout *out, const struct lys_module *mod)
529 {
530     int first = 1, i;
531 
532     ly_print(out, "%-*s", INDENT_LEN, "Augments: ");
533     if (mod->augment_size) {
534         ly_print(out, "\"%s\"\n", mod->augment[0].target_name);
535         i = 1;
536         first = 0;
537 
538         for (; i < mod->augment_size; ++i) {
539             ly_print(out, "%*s\"%s\"\n", INDENT_LEN, "", mod->augment[i].target_name);
540         }
541     }
542 
543     if (first) {
544         ly_print(out, "\n");
545     }
546 }
547 
548 static void
info_print_deviation(struct lyout * out,const struct lys_module * mod)549 info_print_deviation(struct lyout *out, const struct lys_module *mod)
550 {
551     int first = 1, i;
552 
553     ly_print(out, "%-*s", INDENT_LEN, "Deviation: ");
554     if (mod->deviation_size) {
555         ly_print(out, "\"%s\"\n", mod->deviation[0].target_name);
556         i = 1;
557         first = 0;
558 
559         for (; i < mod->deviation_size; ++i) {
560             ly_print(out, "%*s\"%s\"\n", INDENT_LEN, "", mod->deviation[i].target_name);
561         }
562     }
563 
564     if (first) {
565         ly_print(out, "\n");
566     }
567 }
568 
569 static void
info_print_ident_with_include(struct lyout * out,const struct lys_module * mod)570 info_print_ident_with_include(struct lyout *out, const struct lys_module *mod)
571 {
572     int first = 1, i, j;
573 
574     ly_print(out, "%-*s", INDENT_LEN, "Idents: ");
575     if (mod->ident_size) {
576         ly_print(out, "%s\n", mod->ident[0].name);
577         i = 1;
578         first = 0;
579 
580         for (; i < (signed)mod->ident_size; ++i) {
581             ly_print(out, "%*s%s\n", INDENT_LEN, "", mod->ident[i].name);
582         }
583     }
584 
585     for (j = 0; j < mod->inc_size; ++j) {
586         if (mod->inc[j].submodule->ident_size) {
587             if (first) {
588                 ly_print(out, "%s (%s)\n", mod->inc[j].submodule->ident[0].name, mod->inc[j].submodule->name);
589                 i = 1;
590             } else {
591                 i = 0;
592             }
593             first = 0;
594 
595             for (; i < (signed)mod->inc[j].submodule->ident_size; ++i) {
596                 ly_print(out, "%*s%s (%s)\n", INDENT_LEN, "", mod->inc[j].submodule->ident[i].name, mod->inc[j].submodule->name);
597             }
598         }
599     }
600 
601     if (first) {
602         ly_print(out, "\n");
603     }
604 }
605 
606 static void
info_print_features_with_include(struct lyout * out,const struct lys_module * mod)607 info_print_features_with_include(struct lyout *out, const struct lys_module *mod)
608 {
609     int first = 1, i, j;
610 
611     ly_print(out, "%-*s", INDENT_LEN, "Features: ");
612     if (mod->features_size) {
613         ly_print(out, "%s\n", mod->features[0].name);
614         i = 1;
615         first = 0;
616 
617         for (; i < mod->features_size; ++i) {
618             ly_print(out, "%*s%s\n", INDENT_LEN, "", mod->features[i].name);
619         }
620     }
621 
622     for (j = 0; j < mod->inc_size; ++j) {
623         if (mod->inc[j].submodule->features_size) {
624             if (first) {
625                 ly_print(out, "%s (%s)\n", mod->inc[j].submodule->features[0].name, mod->inc[j].submodule->name);
626                 i = 1;
627             } else {
628                 i = 0;
629             }
630             first = 0;
631 
632             for (; i < mod->inc[j].submodule->features_size; ++i) {
633                 ly_print(out, "%*s%s (%s)\n", INDENT_LEN, "", mod->inc[j].submodule->features[i].name, mod->inc[j].submodule->name);
634             }
635         }
636     }
637 
638     if (first) {
639         ly_print(out, "\n");
640     }
641 }
642 
643 static void
info_print_data_mainmod_with_include(struct lyout * out,const struct lys_module * mod)644 info_print_data_mainmod_with_include(struct lyout *out, const struct lys_module *mod)
645 {
646     int first = 1, from_include;
647     struct lys_node *node;
648     const struct lys_module *mainmod = lys_main_module(mod);
649 
650     ly_print(out, "%-*s", INDENT_LEN, "Data: ");
651 
652     if (mainmod->data) {
653         LY_TREE_FOR(mainmod->data, node) {
654             if (node->module != mod) {
655                 if (mainmod != mod) {
656                     continue;
657                 } else {
658                     from_include = 1;
659                 }
660             } else {
661                 from_include = 0;
662             }
663 
664             if (!lys_parent(node) && !strcmp(node->name, "config") && !strcmp(node->module->name, "ietf-netconf")) {
665                 /* node added by libyang, not actually in the model */
666                 continue;
667             }
668 
669             if (first) {
670                 ly_print(out, "%s \"%s\"%s%s%s\n", strnodetype(node->nodetype), node->name, (from_include ? " (" : ""),
671                                                    (from_include ? node->module->name : ""), (from_include ? ")" : ""));
672                 first = 0;
673             } else {
674                 ly_print(out, "%*s%s \"%s\"%s%s%s\n", INDENT_LEN, "", strnodetype(node->nodetype), node->name,
675                         (from_include ? " (" : ""), (from_include ? node->module->name : ""), (from_include ? ")" : ""));
676             }
677         }
678     }
679 
680     if (first) {
681         ly_print(out, "\n");
682     }
683 }
684 
685 static void
info_print_typedef_detail(struct lyout * outf,const struct lys_tpdf * tpdf,int * UNUSED (first))686 info_print_typedef_detail(struct lyout *outf, const struct lys_tpdf *tpdf, int * UNUSED(first))
687 {
688     ly_print(outf, "%-*s%s\n", INDENT_LEN, "Typedef: ", tpdf->name);
689     ly_print(outf, "%-*s%s\n", INDENT_LEN, "Module: ", tpdf->module->name);
690     info_print_text(outf, tpdf->dsc, "Desc: ");
691     info_print_text(outf, tpdf->ref, "Reference: ");
692     info_print_flags(outf, tpdf->flags, LYS_STATUS_MASK, 0);
693     info_print_type_detail_(outf, &tpdf->type, 0);
694     info_print_text(outf, tpdf->units, "Units: ");
695     info_print_text(outf, tpdf->dflt, "Default: ");
696 }
697 
698 static void
info_print_ident_detail(struct lyout * out,const struct lys_ident * ident,int * UNUSED (first))699 info_print_ident_detail(struct lyout *out, const struct lys_ident *ident, int * UNUSED(first))
700 {
701     unsigned int i;
702 
703     ly_print(out, "%-*s%s\n", INDENT_LEN, "Identity: ", ident->name);
704     ly_print(out, "%-*s%s\n", INDENT_LEN, "Module: ", ident->module->name);
705     info_print_text(out, ident->dsc, "Desc: ");
706     info_print_text(out, ident->ref, "Reference: ");
707     info_print_flags(out, ident->flags, LYS_STATUS_MASK, 0);
708 
709     ly_print(out, "%-*s", INDENT_LEN, "Base: ");
710     for (i = 0; i < ident->base_size; i++) {
711         ly_print(out, "%*s%s\n", i ? INDENT_LEN : 0, "", ident->base[i]->name);
712     }
713     if (!i) {
714         ly_print(out, "\n");
715     }
716 
717     ly_print(out, "%-*s", INDENT_LEN, "Derived: ");
718     if (ident->der) {
719         for (i = 0; i < ident->der->number; i++) {
720             ly_print(out, "%*s%s\n", i ? INDENT_LEN : 0, "", ((struct lys_ident *)ident->der->set.g[i])->name);
721         }
722         if (!i) {
723             ly_print(out, "\n");
724         }
725     }
726 }
727 
728 static void
info_print_feature_detail(struct lyout * out,const struct lys_feature * feat,int * UNUSED (first))729 info_print_feature_detail(struct lyout *out, const struct lys_feature *feat, int * UNUSED(first))
730 {
731     ly_print(out, "%-*s%s\n", INDENT_LEN, "Feature: ", feat->name);
732     ly_print(out, "%-*s%s\n", INDENT_LEN, "Module: ", feat->module->name);
733     info_print_text(out, feat->dsc, "Desc: ");
734     info_print_text(out, feat->ref, "Reference: ");
735     info_print_flags(out, feat->flags, LYS_STATUS_MASK | LYS_FENABLED, 0);
736     info_print_if_feature(out, feat->module, feat->iffeature, feat->iffeature_size);
737 }
738 
739 static void
info_print_module(struct lyout * out,const struct lys_module * module)740 info_print_module(struct lyout *out, const struct lys_module *module)
741 {
742     ly_print(out, "%-*s%s\n", INDENT_LEN, "Module: ", module->name);
743     ly_print(out, "%-*s%s\n", INDENT_LEN, "Namespace: ", module->ns);
744     ly_print(out, "%-*s%s\n", INDENT_LEN, "Prefix: ", module->prefix);
745     info_print_text(out, module->dsc, "Desc: ");
746     info_print_text(out, module->ref, "Reference: ");
747     info_print_text(out, module->org, "Org: ");
748     info_print_text(out, module->contact, "Contact: ");
749     ly_print(out, "%-*s%s\n", INDENT_LEN, "YANG ver: ", (module->version == LYS_VERSION_1_1 ? "1.1" : "1.0"));
750     ly_print(out, "%-*s%s\n", INDENT_LEN, "Deviated: ", (module->deviated ? "yes" : "no"));
751     ly_print(out, "%-*s%s\n", INDENT_LEN, "Implement: ", (module->implemented ? "yes" : "no"));
752     info_print_text(out, module->filepath, "URI: file://");
753 
754     info_print_revision(out, module->rev, module->rev_size);
755     info_print_include(out, module);
756     info_print_import_with_include(out, module);
757     info_print_typedef_with_include(out, module);
758     info_print_ident_with_include(out, module);
759     info_print_features_with_include(out, module);
760     info_print_augment(out, module);
761     info_print_deviation(out, module);
762 
763     info_print_data_mainmod_with_include(out, module);
764 }
765 
766 static void
info_print_submodule(struct lyout * out,const struct lys_submodule * module)767 info_print_submodule(struct lyout *out, const struct lys_submodule *module)
768 {
769     ly_print(out, "%-*s%s\n", INDENT_LEN, "Submodule: ", module->name);
770     ly_print(out, "%-*s%s\n", INDENT_LEN, "Parent: ", module->belongsto->name);
771     ly_print(out, "%-*s%s\n", INDENT_LEN, "Prefix: ", module->prefix);
772     info_print_text(out, module->dsc, "Desc: ");
773     info_print_text(out, module->ref, "Reference: ");
774     info_print_text(out, module->org, "Org: ");
775     info_print_text(out, module->contact, "Contact: ");
776 
777     ly_print(out, "%-*s%s\n", INDENT_LEN, "YANG ver: ", (module->version == 2 ? "1.1" : "1.0"));
778     ly_print(out, "%-*s%s\n", INDENT_LEN, "Deviated: ", (module->deviated ? "yes" : "no"));
779     ly_print(out, "%-*s%s\n", INDENT_LEN, "Implement: ", (module->implemented ? "yes" : "no"));
780 
781     info_print_text(out, module->filepath, "URI: file://");
782 
783     info_print_revision(out, module->rev, module->rev_size);
784     info_print_include(out, (struct lys_module *)module);
785     info_print_import_with_include(out, (struct lys_module *)module);
786     info_print_typedef_with_include(out, (struct lys_module *)module);
787     info_print_ident_with_include(out, (struct lys_module *)module);
788     info_print_features_with_include(out, (struct lys_module *)module);
789     info_print_augment(out, (struct lys_module *)module);
790     info_print_deviation(out, (struct lys_module *)module);
791 
792     info_print_data_mainmod_with_include(out, (struct lys_module *)module);
793 }
794 
795 static void
info_print_container(struct lyout * out,const struct lys_node * node,int * UNUSED (first))796 info_print_container(struct lyout *out, const struct lys_node *node, int *UNUSED(first))
797 {
798     struct lys_node_container *cont = (struct lys_node_container *)node;
799 
800     ly_print(out, "%-*s%s\n", INDENT_LEN, "Container: ", cont->name);
801     ly_print(out, "%-*s%s\n", INDENT_LEN, "Module: ", cont->module->name);
802     info_print_text(out, cont->dsc, "Desc: ");
803     info_print_text(out, cont->ref, "Reference: ");
804     info_print_flags(out, cont->flags, LYS_CONFIG_MASK | LYS_STATUS_MASK, 0);
805     info_print_text(out, cont->presence, "Presence: ");
806     info_print_if_feature(out, cont->module, cont->iffeature, cont->iffeature_size);
807     info_print_when(out, cont->when);
808     info_print_must(out, cont->must, cont->must_size);
809     info_print_typedef(out, cont->tpdf, cont->tpdf_size);
810 
811     info_print_snode(out, (struct lys_node *)cont, cont->child, "Children:");
812 }
813 
814 static void
info_print_choice(struct lyout * out,const struct lys_node * node,int * UNUSED (first))815 info_print_choice(struct lyout *out, const struct lys_node *node, int *UNUSED(first))
816 {
817     struct lys_node_choice *choice = (struct lys_node_choice *)node;
818 
819     ly_print(out, "%-*s%s\n", INDENT_LEN, "Choice: ", choice->name);
820     ly_print(out, "%-*s%s\n", INDENT_LEN, "Module: ", choice->module->name);
821     info_print_text(out, choice->dsc, "Desc: ");
822     info_print_text(out, choice->ref, "Reference: ");
823     info_print_flags(out, choice->flags, LYS_CONFIG_MASK | LYS_STATUS_MASK | LYS_MAND_MASK, 0);
824     ly_print(out, "%-*s", INDENT_LEN, "Default: ");
825     if (choice->dflt) {
826         ly_print(out, "%s\n", choice->dflt->name);
827     } else {
828         ly_print(out, "\n");
829     }
830     info_print_if_feature(out, choice->module, choice->iffeature, choice->iffeature_size);
831     info_print_when(out, choice->when);
832 
833     info_print_snode(out, (struct lys_node *)choice, choice->child, "Cases:");
834 }
835 
836 static void
info_print_leaf(struct lyout * out,const struct lys_node * node,int * UNUSED (first))837 info_print_leaf(struct lyout *out, const struct lys_node *node, int *UNUSED(first))
838 {
839     struct lys_node_leaf *leaf = (struct lys_node_leaf *)node;
840 
841     ly_print(out, "%-*s%s\n", INDENT_LEN, "Leaf: ", leaf->name);
842     ly_print(out, "%-*s%s\n", INDENT_LEN, "Module: ", leaf->module->name);
843     info_print_text(out, leaf->dsc, "Desc: ");
844     info_print_text(out, leaf->ref, "Reference: ");
845     info_print_flags(out, leaf->flags, LYS_CONFIG_MASK | LYS_STATUS_MASK | LYS_MAND_MASK, 0);
846     info_print_text(out, leaf->type.der->name, "Type: ");
847     info_print_text(out, leaf->units, "Units: ");
848     info_print_text(out, leaf->dflt, "Default: ");
849     info_print_if_feature(out, leaf->module, leaf->iffeature, leaf->iffeature_size);
850     info_print_when(out, leaf->when);
851     info_print_must(out, leaf->must, leaf->must_size);
852 }
853 
854 static void
info_print_leaflist(struct lyout * out,const struct lys_node * node,int * UNUSED (first))855 info_print_leaflist(struct lyout *out, const struct lys_node *node, int *UNUSED(first))
856 {
857     struct lys_node_leaflist *llist = (struct lys_node_leaflist *)node;
858 
859     ly_print(out, "%-*s%s\n", INDENT_LEN, "Leaflist: ", llist->name);
860     ly_print(out, "%-*s%s\n", INDENT_LEN, "Module: ", llist->module->name);
861     info_print_text(out, llist->dsc, "Desc: ");
862     info_print_text(out, llist->ref, "Reference: ");
863     info_print_flags(out, llist->flags, LYS_CONFIG_MASK | LYS_STATUS_MASK | LYS_USERORDERED, 1);
864     info_print_text(out, llist->type.der->name, "Type: ");
865     info_print_text(out, llist->units, "Units: ");
866     info_print_list_constr(out, llist->min, llist->max);
867     info_print_if_feature(out, llist->module, llist->iffeature, llist->iffeature_size);
868     info_print_when(out, llist->when);
869     info_print_must(out, llist->must, llist->must_size);
870 }
871 
872 static void
info_print_list(struct lyout * out,const struct lys_node * node,int * UNUSED (first))873 info_print_list(struct lyout *out, const struct lys_node *node, int *UNUSED(first))
874 {
875     struct lys_node_list *list = (struct lys_node_list *)node;
876 
877     ly_print(out, "%-*s%s\n", INDENT_LEN, "List: ", list->name);
878     ly_print(out, "%-*s%s\n", INDENT_LEN, "Module: ", list->module->name);
879     info_print_text(out, list->dsc, "Desc: ");
880     info_print_text(out, list->ref, "Reference: ");
881     info_print_flags(out, list->flags, LYS_CONFIG_MASK | LYS_STATUS_MASK | LYS_USERORDERED, 1);
882     info_print_list_constr(out, list->min, list->max);
883     info_print_if_feature(out, list->module, list->iffeature, list->iffeature_size);
884     info_print_when(out, list->when);
885     info_print_must(out, list->must, list->must_size);
886     info_print_text(out, list->keys_str, "Keys: ");
887     info_print_unique(out, list->unique, list->unique_size);
888     info_print_typedef(out, list->tpdf, list->tpdf_size);
889 
890     info_print_snode(out, (struct lys_node *)list, list->child, "Children:");
891 }
892 
893 static void
info_print_anydata(struct lyout * out,const struct lys_node * node,int * UNUSED (first))894 info_print_anydata(struct lyout *out, const struct lys_node *node, int *UNUSED(first))
895 {
896     struct lys_node_anydata *any = (struct lys_node_anydata *)node;
897 
898     ly_print(out, "%-*s%s\n", INDENT_LEN, "%s: ", any->nodetype == LYS_ANYXML ? "Anyxml" : "Anydata", any->name);
899     ly_print(out, "%-*s%s\n", INDENT_LEN, "Module: ", any->module->name);
900     info_print_text(out, any->dsc, "Desc: ");
901     info_print_text(out, any->ref, "Reference: ");
902     info_print_flags(out, any->flags, LYS_CONFIG_MASK | LYS_STATUS_MASK | LYS_MAND_MASK, 0);
903     info_print_if_feature(out, any->module, any->iffeature, any->iffeature_size);
904     info_print_when(out, any->when);
905     info_print_must(out, any->must, any->must_size);
906 }
907 
908 static void
info_print_grouping(struct lyout * out,const struct lys_node * node,int * UNUSED (first))909 info_print_grouping(struct lyout *out, const struct lys_node *node, int * UNUSED(first))
910 {
911     struct lys_node_grp *group = (struct lys_node_grp *)node;
912 
913     ly_print(out, "%-*s%s\n", INDENT_LEN, "Grouping: ", group->name);
914     ly_print(out, "%-*s%s\n", INDENT_LEN, "Module: ", group->module->name);
915     info_print_text(out, group->dsc, "Desc: ");
916     info_print_text(out, group->ref, "Reference: ");
917     info_print_flags(out, group->flags, LYS_STATUS_MASK, 0);
918     info_print_typedef(out, group->tpdf, group->tpdf_size);
919 
920     info_print_snode(out, (struct lys_node *)group, group->child, "Children:");
921 }
922 
923 static void
info_print_case(struct lyout * out,const struct lys_node * node,int * UNUSED (first))924 info_print_case(struct lyout *out, const struct lys_node *node, int *UNUSED(first))
925 {
926     struct lys_node_case *cas = (struct lys_node_case *)node;
927 
928     ly_print(out, "%-*s%s\n", INDENT_LEN, "Case: ", cas->name);
929     ly_print(out, "%-*s%s\n", INDENT_LEN, "Module: ", cas->module->name);
930     info_print_text(out, cas->dsc, "Desc: ");
931     info_print_text(out, cas->ref, "Reference: ");
932     info_print_flags(out, cas->flags, LYS_CONFIG_MASK | LYS_STATUS_MASK, 0);
933     info_print_if_feature(out, cas->module, cas->iffeature, cas->iffeature_size);
934     info_print_when(out, cas->when);
935 
936     info_print_snode(out, (struct lys_node *)cas, cas->child, "Children:");
937 }
938 
939 static void
info_print_input(struct lyout * out,const struct lys_node * node,int * UNUSED (first))940 info_print_input(struct lyout *out, const struct lys_node *node, int *UNUSED(first))
941 {
942     struct lys_node_inout *input = (struct lys_node_inout *)node;
943 
944     assert(lys_parent(node) && lys_parent(node)->nodetype == LYS_RPC);
945 
946     ly_print(out, "%-*s%s\n", INDENT_LEN, "Input of: ", lys_parent(node)->name);
947     info_print_typedef(out, input->tpdf, input->tpdf_size);
948     info_print_must(out, input->must, input->must_size);
949 
950     info_print_snode(out, (struct lys_node *)input, input->child, "Children:");
951 }
952 
953 static void
info_print_output(struct lyout * out,const struct lys_node * node,int * UNUSED (first))954 info_print_output(struct lyout *out, const struct lys_node *node, int *UNUSED(first))
955 {
956     struct lys_node_inout *output = (struct lys_node_inout *)node;
957 
958     assert(lys_parent(node) && lys_parent(node)->nodetype == LYS_RPC);
959 
960     ly_print(out, "%-*s%s\n", INDENT_LEN, "Output of: ", lys_parent(node)->name);
961     info_print_typedef(out, output->tpdf, output->tpdf_size);
962     info_print_must(out, output->must, output->must_size);
963 
964     info_print_snode(out, (struct lys_node *)output, output->child, "Children:");
965 }
966 
967 static void
info_print_notif(struct lyout * out,const struct lys_node * node,int * UNUSED (first))968 info_print_notif(struct lyout *out, const struct lys_node *node, int *UNUSED(first))
969 {
970     struct lys_node_notif *ntf = (struct lys_node_notif *)node;
971 
972     ly_print(out, "%-*s%s\n", INDENT_LEN, "Notif: ", ntf->name);
973     ly_print(out, "%-*s%s\n", INDENT_LEN, "Module: ", ntf->module->name);
974     info_print_text(out, ntf->dsc, "Desc: ");
975     info_print_text(out, ntf->ref, "Reference: ");
976     info_print_flags(out, ntf->flags, LYS_STATUS_MASK, 0);
977     info_print_if_feature(out, ntf->module, ntf->iffeature, ntf->iffeature_size);
978     info_print_typedef(out, ntf->tpdf, ntf->tpdf_size);
979     info_print_must(out, ntf->must, ntf->must_size);
980 
981     info_print_snode(out, (struct lys_node *)ntf, ntf->child, "Params:");
982 }
983 
984 static void
info_print_rpc(struct lyout * out,const struct lys_node * node,int * UNUSED (first))985 info_print_rpc(struct lyout *out, const struct lys_node *node, int *UNUSED(first))
986 {
987     struct lys_node_rpc_action *rpc = (struct lys_node_rpc_action *)node;
988 
989     ly_print(out, "%-*s%s\n", INDENT_LEN, "RPC: ", rpc->name);
990     ly_print(out, "%-*s%s\n", INDENT_LEN, "Module: ", rpc->module->name);
991     info_print_text(out, rpc->dsc, "Desc: ");
992     info_print_text(out, rpc->ref, "Reference: ");
993     info_print_flags(out, rpc->flags, LYS_STATUS_MASK, 0);
994     info_print_if_feature(out, rpc->module, rpc->iffeature, rpc->iffeature_size);
995     info_print_typedef(out, rpc->tpdf, rpc->tpdf_size);
996 
997     info_print_snode(out, (struct lys_node *)rpc, rpc->child, "Data:");
998 }
999 
1000 static void
info_print_action(struct lyout * out,const struct lys_node * node,int * UNUSED (first))1001 info_print_action(struct lyout *out, const struct lys_node *node, int *UNUSED(first))
1002 {
1003     struct lys_node_rpc_action *act = (struct lys_node_rpc_action *)node;
1004 
1005     ly_print(out, "%-*s%s\n", INDENT_LEN, "Action: ", act->name);
1006     ly_print(out, "%-*s%s\n", INDENT_LEN, "Module: ", act->module->name);
1007     info_print_text(out, act->dsc, "Desc: ");
1008     info_print_text(out, act->ref, "Reference: ");
1009     info_print_flags(out, act->flags, LYS_STATUS_MASK, 0);
1010     info_print_if_feature(out, act->module, act->iffeature, act->iffeature_size);
1011     info_print_typedef(out, act->tpdf, act->tpdf_size);
1012 
1013     info_print_snode(out, (struct lys_node *)act, act->child, "Data:");
1014 }
1015 
1016 int
info_print_model(struct lyout * out,const struct lys_module * module,const char * target_schema_path)1017 info_print_model(struct lyout *out, const struct lys_module *module, const char *target_schema_path)
1018 {
1019     int rc = EXIT_SUCCESS;
1020 
1021     if (!target_schema_path) {
1022         if (module->type == 0) {
1023             info_print_module(out, module);
1024         } else {
1025             info_print_submodule(out, (struct lys_submodule *)module);
1026         }
1027     } else {
1028         rc = lys_print_target(out, module, target_schema_path,
1029                               info_print_typedef_detail,
1030                               info_print_ident_detail,
1031                               info_print_feature_detail,
1032                               info_print_type_detail,
1033                               info_print_grouping,
1034                               info_print_container,
1035                               info_print_choice,
1036                               info_print_leaf,
1037                               info_print_leaflist,
1038                               info_print_list,
1039                               info_print_anydata,
1040                               info_print_case,
1041                               info_print_notif,
1042                               info_print_rpc,
1043                               info_print_action,
1044                               info_print_input,
1045                               info_print_output);
1046     }
1047     ly_print_flush(out);
1048 
1049     return rc;
1050 }
1051