blob: bce67e0e387040bbd4d7d5177f1db25351cc7294 [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
Radek Krejciefdd0ce2015-05-26 16:48:29 +02002 * @file printer/yang.c
Radek Krejcida04f4a2015-05-21 12:54:09 +02003 * @author Radek Krejci <rkrejci@cesnet.cz>
Radek Krejciefdd0ce2015-05-26 16:48:29 +02004 * @brief YANG printer for libyang data model structure
Radek Krejcida04f4a2015-05-21 12:54:09 +02005 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 */
21
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25
Radek Krejciefdd0ce2015-05-26 16:48:29 +020026#include "../common.h"
27#include "../tree.h"
Radek Krejcida04f4a2015-05-21 12:54:09 +020028
29#define INDENT ""
30#define LEVEL (level*2)
31
Michal Vasko5bbae102015-06-16 12:16:44 +020032static void yang_print_mnode(FILE *f, int level, struct ly_mnode *mnode, int mask);
Radek Krejcida04f4a2015-05-21 12:54:09 +020033
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020034static void
Michal Vasko5bbae102015-06-16 12:16:44 +020035yang_print_text(FILE *f, int level, const char *name, const char *text)
Radek Krejcida04f4a2015-05-21 12:54:09 +020036{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020037 const char *s, *t;
Radek Krejcida04f4a2015-05-21 12:54:09 +020038
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020039 fprintf(f, "%*s%s\n", LEVEL, INDENT, name);
40 level++;
Radek Krejcida04f4a2015-05-21 12:54:09 +020041
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020042 fprintf(f, "%*s\"", LEVEL, INDENT);
43 t = text;
44 while ((s = strchr(t, '\n'))) {
Michal Vasko5bbae102015-06-16 12:16:44 +020045 fwrite(t, sizeof *t, (s - t) + 1, f);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020046 t = s + 1;
47 fprintf(f, "%*s", LEVEL, INDENT);
48 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020049
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020050 fprintf(f, "%s\";\n\n", t);
51 level--;
Radek Krejcida04f4a2015-05-21 12:54:09 +020052
53}
54
55/*
56 * Covers:
57 * description, reference, status
58 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020059static void
Michal Vasko5bbae102015-06-16 12:16:44 +020060yang_print_mnode_common(FILE *f, int level, struct ly_mnode *mnode)
Radek Krejcida04f4a2015-05-21 12:54:09 +020061{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020062 if (mnode->flags & LY_NODE_STATUS_CURR) {
63 fprintf(f, "%*sstatus \"current\";\n", LEVEL, INDENT);
64 } else if (mnode->flags & LY_NODE_STATUS_DEPRC) {
65 fprintf(f, "%*sstatus \"deprecated\";\n", LEVEL, INDENT);
66 } else if (mnode->flags & LY_NODE_STATUS_OBSLT) {
67 fprintf(f, "%*sstatus \"obsolete\";\n", LEVEL, INDENT);
68 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020069
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020070 if (mnode->dsc) {
71 yang_print_text(f, level, "description", mnode->dsc);
72 }
73 if (mnode->ref) {
74 yang_print_text(f, level, "reference", mnode->ref);
75 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020076}
77
78/*
79 * Covers:
Michal Vasko2b8faed2015-06-09 12:51:20 +020080 * config, mandatory
Radek Krejcida04f4a2015-05-21 12:54:09 +020081 * description, reference, status
82 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020083static void
Michal Vasko5bbae102015-06-16 12:16:44 +020084yang_print_mnode_common2(FILE *f, int level, struct ly_mnode *mnode)
Radek Krejcida04f4a2015-05-21 12:54:09 +020085{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020086 if (!mnode->parent || (mnode->parent->flags & LY_NODE_CONFIG_MASK) != (mnode->flags & LY_NODE_CONFIG_MASK)) {
87 /* print config only when it differs from the parent or in root */
88 if (mnode->flags & LY_NODE_CONFIG_W) {
89 fprintf(f, "%*sconfig \"true\";\n", LEVEL, INDENT);
90 } else if (mnode->flags & LY_NODE_CONFIG_R) {
91 fprintf(f, "%*sconfig \"false\";\n", LEVEL, INDENT);
92 }
93 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020094
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020095 if (mnode->flags & LY_NODE_MAND_TRUE) {
96 fprintf(f, "%*smandatory \"true\";\n", LEVEL, INDENT);
97 } else if (mnode->flags & LY_NODE_MAND_FALSE) {
98 fprintf(f, "%*smandatory \"false\";\n", LEVEL, INDENT);
99 }
Michal Vasko2b8faed2015-06-09 12:51:20 +0200100
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200101 yang_print_mnode_common(f, level, mnode);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200102}
103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200104static void
Michal Vasko5bbae102015-06-16 12:16:44 +0200105yang_print_type(FILE *f, int level, struct ly_module *module, struct ly_type *type)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200106{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200107 int i;
Radek Krejci25d782a2015-05-22 15:03:23 +0200108
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200109 if (type->prefix) {
110 fprintf(f, "%*stype %s:%s {\n", LEVEL, INDENT, type->prefix, type->der->name);
111 } else {
112 fprintf(f, "%*stype %s {\n", LEVEL, INDENT, type->der->name);
113 }
114 level++;
115 switch (type->base) {
116 case LY_TYPE_BINARY:
117 if (type->info.binary.length != NULL) {
118 fprintf(f, "%*slength \"%s\";\n", LEVEL, INDENT, type->info.binary.length);
119 }
120 break;
121 case LY_TYPE_BITS:
122 for (i = 0; i < type->info.bits.count; ++i) {
123 fprintf(f, "%*sbit %s {\n", LEVEL, INDENT, type->info.bits.bit[i].value);
124 level++;
125 yang_print_mnode_common(f, level, (struct ly_mnode *)&type->info.bits.bit[i]);
126 fprintf(f, "%*sposition %u;\n", LEVEL, INDENT, type->info.bits.bit[i].pos);
127 level--;
128 fprintf(f, "%*s}\n", LEVEL, INDENT);
129 }
130 break;
131 case LY_TYPE_DEC64:
132 fprintf(f, "%*sfraction-digits %d;\n", LEVEL, INDENT, type->info.dec64.dig);
133 /* TODO range incomplete */
134 break;
135 case LY_TYPE_ENUM:
136 for (i = 0; i < type->info.enums.count; i++) {
137 fprintf(f, "%*senum %s {\n", LEVEL, INDENT, type->info.enums.list[i].name);
138 level++;
139 yang_print_mnode_common(f, level, (struct ly_mnode *)&type->info.enums.list[i]);
140 fprintf(f, "%*svalue %d;\n", LEVEL, INDENT, type->info.enums.list[i].value);
141 level--;
142 fprintf(f, "%*s}\n", LEVEL, INDENT);
143 }
144 break;
145 case LY_TYPE_IDENT:
146 if (module == type->info.ident.ref->module) {
147 fprintf(f, "%*sbase %s;\n", LEVEL, INDENT, type->info.ident.ref->name);
148 } else {
149 fprintf(f, "%*sbase %s:%s;\n", LEVEL, INDENT, type->info.ident.ref->module->prefix,
150 type->info.ident.ref->name);
151 }
152 break;
153 case LY_TYPE_INST:
154 /* TODO */
155 break;
156 case LY_TYPE_INT8:
157 case LY_TYPE_INT16:
158 case LY_TYPE_INT32:
159 case LY_TYPE_INT64:
160 case LY_TYPE_UINT8:
161 case LY_TYPE_UINT16:
162 case LY_TYPE_UINT32:
163 case LY_TYPE_UINT64:
164 /* TODO wrong - incomplete */
165 /*if (type->info.num.range != NULL) {
166 * fprintf(f, "%*srange \"%s\";\n", LEVEL, INDENT, type->info.num.range);
167 * } */
168 break;
169 case LY_TYPE_LEAFREF:
170 fprintf(f, "%*spath \"%s\";\n", LEVEL, INDENT, type->info.lref.path);
171 break;
172 case LY_TYPE_STRING:
173 /* TODO length, pattern (same as range) incomplete */
174 break;
175 case LY_TYPE_UNION:
176 for (i = 0; i < type->info.uni.count; ++i) {
177 yang_print_type(f, level, module, &type->info.uni.type[i]);
178 }
179 break;
180 default:
181 /* other types do not have substatements */
182 break;
183 }
184 level--;
185 fprintf(f, "%*s}\n", LEVEL, INDENT);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200186}
187
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200188static void
Michal Vasko5bbae102015-06-16 12:16:44 +0200189yang_print_must(FILE *f, int level, struct ly_must *must)
Michal Vasko7f976ee2015-06-09 13:55:41 +0200190{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200191 fprintf(f, "%*smust \"%s\" {\n", LEVEL, INDENT, must->cond);
192 level++;
Michal Vasko7f976ee2015-06-09 13:55:41 +0200193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200194 if (must->eapptag != NULL) {
195 fprintf(f, "%*serror-app-tag \"%s\";\n", LEVEL, INDENT, must->eapptag);
196 }
Michal Vasko7f976ee2015-06-09 13:55:41 +0200197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200198 if (must->emsg != NULL) {
199 yang_print_text(f, level, "error-message", must->emsg);
200 }
201 if (must->dsc != NULL) {
202 yang_print_text(f, level, "description", must->dsc);
203 }
204 if (must->ref != NULL) {
205 yang_print_text(f, level, "reference", must->ref);
206 }
Michal Vasko7f976ee2015-06-09 13:55:41 +0200207
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200208 level--;
209 fprintf(f, "%*s}\n", LEVEL, INDENT);
Michal Vasko7f976ee2015-06-09 13:55:41 +0200210}
211
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200212static void
Michal Vasko5bbae102015-06-16 12:16:44 +0200213yang_print_refine(FILE *f, int level, struct ly_refine *refine)
Michal Vasko00b7cfe2015-06-09 13:56:38 +0200214{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200215 int i;
Michal Vasko00b7cfe2015-06-09 13:56:38 +0200216
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200217 fprintf(f, "%*srefine \"%s\" {\n", LEVEL, INDENT, refine->target);
218 level++;
Michal Vasko00b7cfe2015-06-09 13:56:38 +0200219
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200220 yang_print_mnode_common2(f, level, (struct ly_mnode *)refine);
Michal Vasko00b7cfe2015-06-09 13:56:38 +0200221
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200222 for (i = 0; i < refine->must_size; ++i) {
223 yang_print_must(f, level, &refine->must[i]);
224 }
Michal Vasko00b7cfe2015-06-09 13:56:38 +0200225
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200226 if (refine->target_type & (LY_NODE_LEAF | LY_NODE_CHOICE)) {
227 if (refine->mod.dflt != NULL) {
228 fprintf(f, "%*sdefault \"%s\";\n", LEVEL, INDENT, refine->mod.dflt);
229 }
230 } else if (refine->target_type == LY_NODE_CONTAINER) {
231 if (refine->mod.presence != NULL) {
232 yang_print_text(f, level, "presence", refine->mod.presence);
233 }
234 } else if (refine->target_type & (LY_NODE_LIST | LY_NODE_LEAFLIST)) {
235 if (refine->mod.list.min > 0) {
236 fprintf(f, "%*smin-elements %u;\n", LEVEL, INDENT, refine->mod.list.min);
237 }
238 if (refine->mod.list.max > 0) {
239 fprintf(f, "%*smax-elements %u;\n", LEVEL, INDENT, refine->mod.list.max);
240 }
241 }
Michal Vasko00b7cfe2015-06-09 13:56:38 +0200242
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200243 level--;
244 fprintf(f, "%*s}\n", LEVEL, INDENT);
Michal Vasko00b7cfe2015-06-09 13:56:38 +0200245}
246
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200247static void
Michal Vasko5bbae102015-06-16 12:16:44 +0200248yang_print_typedef(FILE *f, int level, struct ly_module *module, struct ly_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200249{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200250 fprintf(f, "%*stypedef %s {\n", LEVEL, INDENT, tpdf->name);
251 level++;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200252
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200253 yang_print_mnode_common(f, level, (struct ly_mnode *)tpdf);
254 yang_print_type(f, level, module, &tpdf->type);
255 if (tpdf->units != NULL) {
256 fprintf(f, "%*sunits \"%s\";\n", LEVEL, INDENT, tpdf->units);
257 }
258 if (tpdf->dflt != NULL) {
259 fprintf(f, "%*sdefault \"%s\";\n", LEVEL, INDENT, tpdf->dflt);
260 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200261
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200262 level--;
263 fprintf(f, "%*s}\n", LEVEL, INDENT);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200264}
265
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200266static void
Michal Vasko5bbae102015-06-16 12:16:44 +0200267yang_print_identity(FILE *f, int level, struct ly_ident *ident)
Radek Krejci6793db02015-05-22 17:49:54 +0200268{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200269 fprintf(f, "%*sidentity %s {\n", LEVEL, INDENT, ident->name);
270 level++;
Radek Krejci6793db02015-05-22 17:49:54 +0200271
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200272 yang_print_mnode_common(f, level, (struct ly_mnode *)ident);
273 if (ident->base) {
274 if (ident->base->module == ident->module) {
275 fprintf(f, "%*sbase %s;\n", LEVEL, INDENT, ident->base->name);
276 } else {
277 fprintf(f, "%*sbase %s:%s;\n", LEVEL, INDENT, ident->base->module->prefix, ident->base->name);
278 }
279 }
Radek Krejci6793db02015-05-22 17:49:54 +0200280
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200281 level--;
282 fprintf(f, "%*s}\n", LEVEL, INDENT);
Radek Krejci6793db02015-05-22 17:49:54 +0200283
284}
285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200286static void
Michal Vasko5bbae102015-06-16 12:16:44 +0200287yang_print_container(FILE *f, int level, struct ly_mnode *mnode)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200288{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200289 int i;
290 struct ly_mnode *sub;
291 struct ly_mnode_container *cont = (struct ly_mnode_container *)mnode;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200292
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200293 fprintf(f, "%*scontainer %s {\n", LEVEL, INDENT, mnode->name);
Michal Vasko7f976ee2015-06-09 13:55:41 +0200294
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200295 level++;
296 if (cont->presence != NULL) {
297 yang_print_text(f, level, "presence", cont->presence);
298 }
Michal Vasko7f976ee2015-06-09 13:55:41 +0200299
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200300 for (i = 0; i < cont->must_size; i++) {
301 yang_print_must(f, level, &cont->must[i]);
302 }
Michal Vasko7f976ee2015-06-09 13:55:41 +0200303
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200304 yang_print_mnode_common2(f, level, mnode);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200305
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200306 for (i = 0; i < cont->tpdf_size; i++) {
307 yang_print_typedef(f, level, mnode->module, &cont->tpdf[i]);
308 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200309
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200310 LY_TREE_FOR(mnode->child, sub) {
311 yang_print_mnode(f, level, sub,
312 LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST |
313 LY_NODE_USES | LY_NODE_GROUPING | LY_NODE_ANYXML);
314 }
Michal Vaskoc1329bc2015-06-09 13:58:18 +0200315
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200316 level--;
317 fprintf(f, "%*s}\n", LEVEL, INDENT);
Michal Vaskoc1329bc2015-06-09 13:58:18 +0200318}
319
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200320static void
Michal Vasko5bbae102015-06-16 12:16:44 +0200321yang_print_case(FILE *f, int level, struct ly_mnode *mnode)
Michal Vaskoc1329bc2015-06-09 13:58:18 +0200322{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200323 struct ly_mnode *sub;
324 struct ly_mnode_case *cas = (struct ly_mnode_case *)mnode;
Michal Vaskoc1329bc2015-06-09 13:58:18 +0200325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200326 fprintf(f, "%*scase %s {\n", LEVEL, INDENT, cas->name);
327 level++;
328 yang_print_mnode_common2(f, level, mnode);
Michal Vaskoc1329bc2015-06-09 13:58:18 +0200329
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200330 LY_TREE_FOR(mnode->child, sub) {
331 yang_print_mnode(f, level, sub,
332 LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST |
333 LY_NODE_USES | LY_NODE_ANYXML);
334 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200335
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200336 level--;
337 fprintf(f, "%*s}\n", LEVEL, INDENT);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200338}
339
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200340static void
Michal Vasko5bbae102015-06-16 12:16:44 +0200341yang_print_choice(FILE *f, int level, struct ly_mnode *mnode)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200342{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200343 struct ly_mnode *sub;
344 struct ly_mnode_choice *choice = (struct ly_mnode_choice *)mnode;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200345
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200346 fprintf(f, "%*schoice %s {\n", LEVEL, INDENT, mnode->name);
Michal Vasko16083662015-06-09 14:00:45 +0200347
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200348 level++;
349 if (choice->dflt != NULL) {
350 fprintf(f, "%*sdefault \"%s\";\n", LEVEL, INDENT, choice->dflt->name);
351 }
Michal Vasko16083662015-06-09 14:00:45 +0200352
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200353 yang_print_mnode_common2(f, level, mnode);
354 LY_TREE_FOR(mnode->child, sub) {
355 yang_print_mnode(f, level, sub,
356 LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST | LY_NODE_ANYXML | LY_NODE_CASE);
357 }
358 level--;
359 fprintf(f, "%*s}\n", LEVEL, INDENT);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200360}
361
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200362static void
Michal Vasko5bbae102015-06-16 12:16:44 +0200363yang_print_leaf(FILE *f, int level, struct ly_mnode *mnode)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200364{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200365 int i;
366 struct ly_mnode_leaf *leaf = (struct ly_mnode_leaf *)mnode;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200367
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200368 fprintf(f, "%*sleaf %s {\n", LEVEL, INDENT, mnode->name);
Michal Vasko16083662015-06-09 14:00:45 +0200369
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200370 level++;
371 yang_print_mnode_common2(f, level, mnode);
372 for (i = 0; i < leaf->must_size; i++) {
373 yang_print_must(f, level, &leaf->must[i]);
374 }
375 yang_print_type(f, level, mnode->module, &leaf->type);
376 if (leaf->units != NULL) {
377 fprintf(f, "%*sunits \"%s\";\n", LEVEL, INDENT, leaf->units);
378 }
379 if (leaf->dflt != NULL) {
380 fprintf(f, "%*sdefault \"%s\";\n", LEVEL, INDENT, leaf->dflt);
381 }
382 level--;
Michal Vasko16083662015-06-09 14:00:45 +0200383
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200384 fprintf(f, "%*s}\n", LEVEL, INDENT);
Michal Vasko16083662015-06-09 14:00:45 +0200385}
386
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200387static void
Michal Vasko5bbae102015-06-16 12:16:44 +0200388yang_print_anyxml(FILE *f, int level, struct ly_mnode *mnode)
Michal Vasko16083662015-06-09 14:00:45 +0200389{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200390 int i;
391 struct ly_mnode_anyxml *anyxml = (struct ly_mnode_anyxml *)mnode;
Michal Vasko16083662015-06-09 14:00:45 +0200392
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200393 fprintf(f, "%*sanyxml %s {\n", LEVEL, INDENT, anyxml->name);
394 level++;
395 yang_print_mnode_common2(f, level, mnode);
396 for (i = 0; i < anyxml->must_size; i++) {
397 yang_print_must(f, level, &anyxml->must[i]);
398 }
399 level--;
400 fprintf(f, "%*s}\n", LEVEL, INDENT);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200401}
402
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200403static void
Michal Vasko5bbae102015-06-16 12:16:44 +0200404yang_print_leaflist(FILE *f, int level, struct ly_mnode *mnode)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200405{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200406 int i;
407 struct ly_mnode_leaflist *llist = (struct ly_mnode_leaflist *)mnode;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200408
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200409 fprintf(f, "%*sleaf-list %s {\n", LEVEL, INDENT, mnode->name);
Michal Vasko16083662015-06-09 14:00:45 +0200410
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200411 level++;
412 yang_print_mnode_common2(f, level, mnode);
413 if (llist->flags & LY_NODE_USERORDERED) {
414 fprintf(f, "%*sordered-by user;\n", LEVEL, INDENT);
415 }
416 if (llist->min > 0) {
417 fprintf(f, "%*smin-elements %u;\n", LEVEL, INDENT, llist->min);
418 }
419 if (llist->max > 0) {
420 fprintf(f, "%*smax-elements %u;\n", LEVEL, INDENT, llist->max);
421 }
422 for (i = 0; i < llist->must_size; i++) {
423 yang_print_must(f, level, &llist->must[i]);
424 }
425 yang_print_type(f, level, mnode->module, &llist->type);
426 if (llist->units != NULL) {
427 fprintf(f, "%*sunits \"%s\";\n", LEVEL, INDENT, llist->units);
428 }
429 level--;
Michal Vasko16083662015-06-09 14:00:45 +0200430
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200431 fprintf(f, "%*s}\n", LEVEL, INDENT);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200432}
433
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200434static void
Michal Vasko5bbae102015-06-16 12:16:44 +0200435yang_print_list(FILE *f, int level, struct ly_mnode *mnode)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200436{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200437 int i, j;
438 struct ly_mnode *sub;
439 struct ly_unique *uniq;
440 struct ly_mnode_list *list = (struct ly_mnode_list *)mnode;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200441
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200442 fprintf(f, "%*slist %s {\n", LEVEL, INDENT, mnode->name);
443 level++;
444 yang_print_mnode_common2(f, level, mnode);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200445
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200446 if (list->keys_size) {
447 fprintf(f, "%*skey \"", LEVEL, INDENT);
448 for (i = 0; i < list->keys_size; i++) {
449 fprintf(f, "%s%s", list->keys[i]->name, i + 1 < list->keys_size ? " " : "");
450 }
451 fprintf(f, "\";\n");
452 }
Radek Krejcid7f0d012015-05-25 15:04:52 +0200453
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200454 for (i = 0; i < list->unique_size; i++) {
455 uniq = &list->unique[i];
456 fprintf(f, "%*sunique \"", LEVEL, INDENT);
457 for (j = 0; j < uniq->leafs_size; j++) {
458 fprintf(f, "%s%s", uniq->leafs[j]->name, j + 1 < uniq->leafs_size ? " " : "");
459 }
460 fprintf(f, "\";\n");
461 }
Michal Vaskodff818b2015-06-09 14:01:12 +0200462
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200463 if (list->flags & LY_NODE_USERORDERED) {
464 fprintf(f, "%*sordered-by user;\n", LEVEL, INDENT);
465 }
466 if (list->min > 0) {
467 fprintf(f, "%*smin-elements %u;\n", LEVEL, INDENT, list->min);
468 }
469 if (list->max > 0) {
470 fprintf(f, "%*smax-elements %u;\n", LEVEL, INDENT, list->max);
471 }
472 for (i = 0; i < list->must_size; i++) {
473 yang_print_must(f, level, &list->must[i]);
474 }
Michal Vaskodff818b2015-06-09 14:01:12 +0200475
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200476 for (i = 0; i < list->tpdf_size; i++) {
477 yang_print_typedef(f, level, list->module, &list->tpdf[i]);
478 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200479
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200480 LY_TREE_FOR(mnode->child, sub) {
481 yang_print_mnode(f, level, sub,
482 LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST |
483 LY_NODE_USES | LY_NODE_GROUPING | LY_NODE_ANYXML);
484 }
485 level--;
486 fprintf(f, "%*s}\n", LEVEL, INDENT);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200487}
488
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200489static void
Michal Vasko5bbae102015-06-16 12:16:44 +0200490yang_print_grouping(FILE *f, int level, struct ly_mnode *mnode)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200491{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200492 int i;
493 struct ly_mnode *node;
494 struct ly_mnode_grp *grp = (struct ly_mnode_grp *)mnode;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200495
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200496 fprintf(f, "%*sgrouping %s {\n", LEVEL, INDENT, mnode->name);
497 level++;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200498
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200499 yang_print_mnode_common(f, level, mnode);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200500
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200501 for (i = 0; i < grp->tpdf_size; i++) {
502 yang_print_typedef(f, level, mnode->module, &grp->tpdf[i]);
503 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200504
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200505 LY_TREE_FOR(mnode->child, node) {
506 yang_print_mnode(f, level, node,
507 LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST |
508 LY_NODE_USES | LY_NODE_GROUPING | LY_NODE_ANYXML);
509 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200510
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200511 level--;
512 fprintf(f, "%*s}\n", LEVEL, INDENT);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200513}
514
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200515static void
Michal Vasko5bbae102015-06-16 12:16:44 +0200516yang_print_uses(FILE *f, int level, struct ly_mnode *mnode)
Radek Krejcic7c9a6c2015-05-25 16:35:06 +0200517{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200518 int i;
519 struct ly_mnode_uses *uses = (struct ly_mnode_uses *)mnode;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +0200520
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200521 fprintf(f, "%*suses %s {\n", LEVEL, INDENT, uses->name);
522 level++;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +0200523
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200524 yang_print_mnode_common(f, level, mnode);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +0200525
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200526 for (i = 0; i < uses->refine_size; i++) {
527 yang_print_refine(f, level, &uses->refine[i]);
528 }
Michal Vasko00b7cfe2015-06-09 13:56:38 +0200529
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200530 level--;
531 fprintf(f, "%*s}\n", LEVEL, INDENT);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +0200532}
533
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200534static void
Michal Vasko5bbae102015-06-16 12:16:44 +0200535yang_print_input_output(FILE *f, int level, struct ly_mnode *mnode)
536{
Michal Vaskof4d3d742015-06-16 11:51:09 +0200537 int i;
538 struct ly_mnode *sub;
Michal Vaskofb69a842015-06-16 12:07:40 +0200539 struct ly_mnode_input_output *inout = (struct ly_mnode_input_output *)mnode;
Michal Vaskof4d3d742015-06-16 11:51:09 +0200540
541 fprintf(f, "%*s%s {\n", LEVEL, INDENT, (inout->nodetype == LY_NODE_INPUT ? "input" : "output"));
542
543 level++;
544 for (i = 0; i < inout->tpdf_size; i++) {
545 yang_print_typedef(f, level, mnode->module, &inout->tpdf[i]);
546 }
547
548 LY_TREE_FOR(mnode->child, sub) {
549 yang_print_mnode(f, level, sub,
550 LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST |
551 LY_NODE_USES | LY_NODE_GROUPING | LY_NODE_ANYXML);
552 }
553
554 level--;
555 fprintf(f, "%*s}\n", LEVEL, INDENT);
556}
557
558static void
559yang_print_rpc(FILE *f, int level, struct ly_mnode *mnode)
560{
561 int i;
562 struct ly_mnode *sub;
563 struct ly_mnode_rpc *rpc = (struct ly_mnode_rpc *)mnode;
564
565 fprintf(f, "%*srpc %s {\n", LEVEL, INDENT, mnode->name);
566
567 level++;
568 yang_print_mnode_common(f, level, mnode);
569
570 for (i = 0; i < rpc->tpdf_size; i++) {
571 yang_print_typedef(f, level, mnode->module, &rpc->tpdf[i]);
572 }
573
574 LY_TREE_FOR(mnode->child, sub) {
575 yang_print_mnode(f, level, sub,
576 LY_NODE_GROUPING | LY_NODE_INPUT | LY_NODE_OUTPUT);
577 }
578
579 level--;
580 fprintf(f, "%*s}\n", LEVEL, INDENT);
581}
582
583static void
584yang_print_notif(FILE *f, int level, struct ly_mnode *mnode) {
585 int i;
586 struct ly_mnode *sub;
587 struct ly_mnode_notif *notif = (struct ly_mnode_notif *)mnode;
588
589 fprintf(f, "%*snotification %s {\n", LEVEL, INDENT, mnode->name);
590
591 level++;
592 yang_print_mnode_common(f, level, mnode);
593
594 for (i = 0; i < notif->tpdf_size; i++) {
595 yang_print_typedef(f, level, mnode->module, &notif->tpdf[i]);
596 }
597
598 LY_TREE_FOR(mnode->child, sub) {
599 yang_print_mnode(f, level, sub,
600 LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST |
601 LY_NODE_USES | LY_NODE_GROUPING | LY_NODE_ANYXML);
602 }
603
604 level--;
605 fprintf(f, "%*s}\n", LEVEL, INDENT);
606}
607
608static void
Michal Vasko5bbae102015-06-16 12:16:44 +0200609yang_print_mnode(FILE *f, int level, struct ly_mnode *mnode, int mask)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200610{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200611 switch (mnode->nodetype & mask) {
612 case LY_NODE_CONTAINER:
613 yang_print_container(f, level, mnode);
614 break;
615 case LY_NODE_CHOICE:
616 yang_print_choice(f, level, mnode);
617 break;
618 case LY_NODE_LEAF:
619 yang_print_leaf(f, level, mnode);
620 break;
621 case LY_NODE_LEAFLIST:
622 yang_print_leaflist(f, level, mnode);
623 break;
624 case LY_NODE_LIST:
625 yang_print_list(f, level, mnode);
626 break;
627 case LY_NODE_USES:
628 yang_print_uses(f, level, mnode);
629 break;
630 case LY_NODE_GROUPING:
631 yang_print_grouping(f, level, mnode);
632 break;
633 case LY_NODE_ANYXML:
634 yang_print_anyxml(f, level, mnode);
635 break;
636 case LY_NODE_CASE:
637 yang_print_case(f, level, mnode);
638 break;
Michal Vaskof4d3d742015-06-16 11:51:09 +0200639 case LY_NODE_INPUT:
640 case LY_NODE_OUTPUT:
641 yang_print_input_output(f, level, mnode);
642 break;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200643 default:
644 break;
645 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200646}
647
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200648int
Michal Vasko5bbae102015-06-16 12:16:44 +0200649yang_print_model(FILE *f, struct ly_module *module)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200650{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200651 unsigned int i;
652 int level = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200653#define LEVEL (level*2)
654
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200655 struct ly_mnode *mnode;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200657 fprintf(f, "module %s {\n", module->name);
658 level++;
Radek Krejcib0594bf2015-05-21 23:51:27 +0200659
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200660 fprintf(f, "%*snamespace \"%s\";\n", LEVEL, INDENT, module->ns);
661 fprintf(f, "%*sprefix \"%s\";\n", LEVEL, INDENT, module->prefix);
Radek Krejcib0594bf2015-05-21 23:51:27 +0200662
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200663 if (module->version) {
664 fprintf(f, "%*syang-version \"%s\";\n", LEVEL, INDENT, module->version == 1 ? "1.0" : "1.1");
665 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200666
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200667 for (i = 0; i < module->imp_size; i++) {
668 fprintf(f, "%*simport \"%s\" {\n", LEVEL, INDENT, module->imp[i].module->name);
669 level++;
670 yang_print_text(f, level, "prefix", module->imp[i].prefix);
671 if (module->imp[i].rev[0]) {
672 yang_print_text(f, level, "revision-date", module->imp[i].rev);
673 }
674 level--;
675 fprintf(f, "%*s}\n", LEVEL, INDENT);
676 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200677
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200678 for (i = 0; i < module->inc_size; i++) {
679 if (module->inc[i].rev[0]) {
680 fprintf(f, "%*sinclude \"%s\" {\n", LEVEL, INDENT, module->inc[i].submodule->name);
681 yang_print_text(f, level + 1, "revision-date", module->imp[i].rev);
682 fprintf(f, "%*s}\n", LEVEL, INDENT);
683 } else {
684 fprintf(f, "%*sinclude \"%s\";\n", LEVEL, INDENT, module->inc[i].submodule->name);
685 }
686 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200687
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200688 if (module->org) {
689 yang_print_text(f, level, "organization", module->org);
690 }
691 if (module->contact) {
692 yang_print_text(f, level, "contact", module->contact);
693 }
694 if (module->dsc) {
695 yang_print_text(f, level, "description", module->dsc);
696 }
697 if (module->ref) {
698 yang_print_text(f, level, "reference", module->ref);
699 }
700 for (i = 0; i < module->rev_size; i++) {
701 if (module->rev[i].dsc || module->rev[i].ref) {
702 fprintf(f, "%*srevision \"%s\" {\n", LEVEL, INDENT, module->rev[i].date);
703 level++;
704 if (module->rev[i].dsc) {
705 yang_print_text(f, level, "description", module->rev[i].dsc);
706 }
707 if (module->rev[i].ref) {
708 yang_print_text(f, level, "reference", module->rev[i].ref);
709 }
710 level--;
711 fprintf(f, "%*s}\n", LEVEL, INDENT);
712 } else {
713 yang_print_text(f, level, "revision", module->rev[i].date);
714 }
715 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200716
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200717 for (i = 0; i < module->ident_size; i++) {
718 yang_print_identity(f, level, &module->ident[i]);
719 }
Radek Krejci6793db02015-05-22 17:49:54 +0200720
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200721 for (i = 0; i < module->tpdf_size; i++) {
722 yang_print_typedef(f, level, module, &module->tpdf[i]);
723 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200724
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200725 LY_TREE_FOR(module->data, mnode) {
726 yang_print_mnode(f, level, mnode,
727 LY_NODE_CHOICE | LY_NODE_CONTAINER | LY_NODE_LEAF | LY_NODE_LEAFLIST | LY_NODE_LIST |
728 LY_NODE_USES | LY_NODE_GROUPING | LY_NODE_ANYXML);
729 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200730
Michal Vaskof4d3d742015-06-16 11:51:09 +0200731 LY_TREE_FOR(module->rpc, mnode) {
732 yang_print_rpc(f, level, mnode);
733 }
734
735 LY_TREE_FOR(module->notif, mnode) {
736 yang_print_notif(f, level, mnode);
737 }
738
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200739 fprintf(f, "}\n");
Radek Krejcida04f4a2015-05-21 12:54:09 +0200740
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200741 return EXIT_SUCCESS;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200742#undef LEVEL
743}