blob: 6dbf2adcd65232051a954342cfe140b52618dd54 [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
2 * @file yin.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief YIN parser for libyang
5 *
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
Radek Krejci812b10a2015-05-28 16:48:25 +020022#include <assert.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020023#include <ctype.h>
Radek Krejci8b4f23c2015-06-02 16:09:25 +020024#include <errno.h>
25#include <limits.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020026#include <stdint.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020027#include <stdlib.h>
28#include <string.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020029#include <stddef.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020030
Radek Krejciefdd0ce2015-05-26 16:48:29 +020031#include "../libyang.h"
32#include "../common.h"
33#include "../context.h"
34#include "../dict.h"
35#include "../parser.h"
Radek Krejcida04f4a2015-05-21 12:54:09 +020036
Radek Krejciefdd0ce2015-05-26 16:48:29 +020037#include "../tree_internal.h"
38#include "../xml.h"
39
Radek Krejcice7fb782015-05-29 16:52:34 +020040enum LY_IDENT {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020041 LY_IDENT_FEATURE,
42 LY_IDENT_IDENTITY,
43 LY_IDENT_TYPE,
44 LY_IDENT_NODE,
45 LY_IDENT_NAME,
46 LY_IDENT_PREFIX
Radek Krejcice7fb782015-05-29 16:52:34 +020047};
48
Radek Krejciefdd0ce2015-05-26 16:48:29 +020049#define LY_NSYIN "urn:ietf:params:xml:ns:yang:yin:1"
Radek Krejcida04f4a2015-05-21 12:54:09 +020050
Radek Krejcice7fb782015-05-29 16:52:34 +020051#define GETVAL(value, node, arg) \
52 value = lyxml_get_attr(node, arg, NULL); \
53 if (!value) { \
54 LOGVAL(VE_MISSARG, LOGLINE(node), arg, node->name); \
55 goto error; \
56 }
57
Radek Krejcib388c152015-06-04 17:03:03 +020058#define OPT_IDENT 0x01
59#define OPT_CONFIG 0x02
60#define OPT_MODULE 0x04
61#define OPT_INHERIT 0x08
62static int read_yin_common(struct ly_module *, struct ly_mnode *, struct ly_mnode *, struct lyxml_elem *, int);
63
Radek Krejci74705112015-06-05 10:25:44 +020064struct mnode_list {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020065 struct ly_mnode *mnode;
66 struct mnode_list *next;
67 unsigned int line;
Radek Krejci74705112015-06-05 10:25:44 +020068};
69
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020070static struct ly_mnode *read_yin_choice(struct ly_module *module, struct ly_mnode *parent, struct lyxml_elem *yin,
71 int resolve, struct mnode_list **unres);
72static struct ly_mnode *read_yin_case(struct ly_module *module, struct ly_mnode *parent, struct lyxml_elem *yin,
73 int resolve, struct mnode_list **unres);
74static struct ly_mnode *read_yin_anyxml(struct ly_module *module, struct ly_mnode *parent, struct lyxml_elem *yin,
75 int resolve);
76static struct ly_mnode *read_yin_container(struct ly_module *module, struct ly_mnode *parent, struct lyxml_elem *yin,
77 int resolve, struct mnode_list **unres);
78static struct ly_mnode *read_yin_leaf(struct ly_module *module, struct ly_mnode *parent, struct lyxml_elem *yin,
79 int resolve);
80static struct ly_mnode *read_yin_leaflist(struct ly_module *module, struct ly_mnode *parent, struct lyxml_elem *yin,
81 int resolve);
82static struct ly_mnode *read_yin_list(struct ly_module *module,struct ly_mnode *parent, struct lyxml_elem *yin,
83 int resolve, struct mnode_list **unres);
84static struct ly_mnode *read_yin_uses(struct ly_module *module, struct ly_mnode *parent, struct lyxml_elem *node,
85 int resolve, struct mnode_list **unres);
86static struct ly_mnode *read_yin_grouping(struct ly_module *module, struct ly_mnode *parent, struct lyxml_elem *node,
87 int resolve, struct mnode_list **unres);
Radek Krejci74705112015-06-05 10:25:44 +020088
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020089static int
90dup_typedef_check(const char *type, struct ly_tpdf *tpdf, int size)
Radek Krejcieac35532015-05-31 19:09:15 +020091{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020092 int i;
Radek Krejcieac35532015-05-31 19:09:15 +020093
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020094 for (i = 0; i < size; i++) {
95 if (!strcmp(type, tpdf[i].name)) {
96 /* name collision */
97 return EXIT_FAILURE;
98 }
99 }
Radek Krejcieac35532015-05-31 19:09:15 +0200100
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200101 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +0200102}
103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200104static int
105dup_prefix_check(const char *prefix, struct ly_module *module)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200106{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200107 int i;
Radek Krejcice7fb782015-05-29 16:52:34 +0200108
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200109 if (!module->type && module->prefix && !strcmp(module->prefix, prefix)) {
110 return EXIT_FAILURE;
111 }
112 for (i = 0; i < module->imp_size; i++) {
113 if (!strcmp(module->imp[i].prefix, prefix)) {
114 return EXIT_FAILURE;
115 }
116 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200117
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200118 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +0200119}
120
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200121static int
122check_identifier(const char *id, enum LY_IDENT type, unsigned int line,
123 struct ly_module *module, struct ly_mnode *parent)
Radek Krejcice7fb782015-05-29 16:52:34 +0200124{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200125 int i;
126 int size;
127 struct ly_tpdf *tpdf;
128 struct ly_mnode *mnode;
Radek Krejcice7fb782015-05-29 16:52:34 +0200129
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200130 assert(id);
Radek Krejcice7fb782015-05-29 16:52:34 +0200131
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200132 /* check id syntax */
133 if (!(id[0] >= 'A' && id[0] <= 'Z') && !(id[0] >= 'a' && id[0] <= 'z') && id[0] != '_') {
134 LOGVAL(VE_INID, line, id, "invalid start character");
135 return EXIT_FAILURE;
136 }
137 for (i = 1; id[i]; i++) {
138 if (!(id[i] >= 'A' && id[i] <= 'Z') && !(id[i] >= 'a' && id[i] <= 'z')
139 && !(id[i] >= '0' && id[i] <= '9') && id[i] != '_' && id[i] != '-' && id[i] != '.') {
140 LOGVAL(VE_INID, line, id, "invalid character");
141 return EXIT_FAILURE;
142 }
143 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200145 if (i > 64) {
146 LOGWRN("Identifier \"%s\" is long, you should use something shorter.", id);
147 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200148
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200149 switch (type) {
150 case LY_IDENT_NAME:
151 /* check uniqueness of the node within its siblings */
152 if (!parent) {
153 break;
154 }
Radek Krejcib4cf2022015-06-03 14:40:05 +0200155
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200156 LY_TREE_FOR(parent->child, mnode) {
157 if (mnode->name == id) {
158 LOGVAL(VE_INID, line, id, "name duplication");
159 return EXIT_FAILURE;
160 }
161 }
162 break;
163 case LY_IDENT_TYPE:
164 assert(module);
Radek Krejcieac35532015-05-31 19:09:15 +0200165
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200166 /* check collision with the built-in types */
167 if (!strcmp(id, "binary") || !strcmp(id, "bits") ||
168 !strcmp(id, "boolean") || !strcmp(id, "decimal64") ||
169 !strcmp(id, "empty") || !strcmp(id, "enumeration") ||
170 !strcmp(id, "identityref") || !strcmp(id, "instance-identifier") ||
171 !strcmp(id, "int8") || !strcmp(id, "int16") ||
172 !strcmp(id, "int32") || !strcmp(id, "int64") ||
173 !strcmp(id, "leafref") || !strcmp(id, "string") ||
174 !strcmp(id, "uint8") || !strcmp(id, "uint16") ||
175 !strcmp(id, "uint32") || !strcmp(id, "uint64") || !strcmp(id, "union")) {
176 LOGVAL(VE_SPEC, line, "Typedef name duplicates built-in type.");
177 return EXIT_FAILURE;
178 }
Radek Krejcieac35532015-05-31 19:09:15 +0200179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200180 /* check locally scoped typedefs (avoid name shadowing) */
181 for (; parent; parent = parent->parent) {
182 switch (parent->nodetype) {
183 case LY_NODE_CONTAINER:
184 size = ((struct ly_mnode_container *)parent)->tpdf_size;
185 tpdf = ((struct ly_mnode_container *)parent)->tpdf;
186 break;
187 case LY_NODE_LIST:
188 size = ((struct ly_mnode_list *)parent)->tpdf_size;
189 tpdf = ((struct ly_mnode_list *)parent)->tpdf;
190 break;
191 case LY_NODE_GROUPING:
192 size = ((struct ly_mnode_grp *)parent)->tpdf_size;
193 tpdf = ((struct ly_mnode_grp *)parent)->tpdf;
194 break;
195 default:
196 continue;
197 }
Radek Krejcieac35532015-05-31 19:09:15 +0200198
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200199 if (dup_typedef_check(id, tpdf, size)) {
200 LOGVAL(VE_DUPID, line, "typedef", id);
201 return EXIT_FAILURE;
202 }
203 }
Radek Krejcieac35532015-05-31 19:09:15 +0200204
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200205 /* check top-level names */
206 if (dup_typedef_check(id, module->tpdf, module->tpdf_size)) {
207 LOGVAL(VE_DUPID, line, "typedef", id);
208 return EXIT_FAILURE;
209 }
Radek Krejcieac35532015-05-31 19:09:15 +0200210
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200211 /* check submodule's top-level names */
212 for (i = 0; i < module->inc_size; i++) {
213 if (dup_typedef_check(id, module->inc[i].submodule->tpdf, module->inc[i].submodule->tpdf_size)) {
214 LOGVAL(VE_DUPID, line, "typedef", id);
215 return EXIT_FAILURE;
216 }
217 }
Radek Krejcieac35532015-05-31 19:09:15 +0200218
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200219 /* check top-level names in the main module */
220 if (module->type) {
221 if (dup_typedef_check(id, ((struct ly_submodule *)module)->belongsto->tpdf,
222 ((struct ly_submodule *)module)->belongsto->tpdf_size)) {
223 LOGVAL(VE_DUPID, line, "typedef", id);
224 return EXIT_FAILURE;
225 }
226 }
Radek Krejcieac35532015-05-31 19:09:15 +0200227
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200228 break;
229 case LY_IDENT_PREFIX:
230 assert(module);
Radek Krejcieac35532015-05-31 19:09:15 +0200231
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200232 if (module->type) {
233 /* go to the main module */
234 module = ((struct ly_submodule *)module)->belongsto;
235 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200237 /* check the main module itself */
238 if (dup_prefix_check(id, module)) {
239 LOGVAL(VE_DUPID, line, "prefix", id);
240 return EXIT_FAILURE;
241 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200242
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200243 /* and all its submodules */
244 for (i = 0; i < module->inc_size; i++) {
245 if (dup_prefix_check(id, (struct ly_module *)module->inc[i].submodule)) {
246 LOGVAL(VE_DUPID, line, "prefix", id);
247 return EXIT_FAILURE;
248 }
249 }
250 break;
251 default:
252 /* no check required */
253 break;
254 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200255
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200256 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +0200257}
258
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200259static int
260check_key(struct ly_mnode_leaf *key, uint8_t flags, struct ly_mnode_leaf **list, int index, unsigned int line,
261 const char *name, int len)
Radek Krejci345ad742015-06-03 11:04:18 +0200262{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200263 char *dup = NULL;
264 int j;
Radek Krejci345ad742015-06-03 11:04:18 +0200265
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200266 /* existence */
267 if (!key) {
268 if (name[len] != '\0') {
269 dup = strdup(name);
270 dup[len] = '\0';
271 name = dup;
272 }
273 LOGVAL(VE_KEY_MISS, line, name);
274 free(dup);
275 return EXIT_FAILURE;
276 }
Radek Krejci345ad742015-06-03 11:04:18 +0200277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200278 /* uniqueness */
279 for (j = index - 1; j >= 0; j--) {
280 if (list[index] == list[j]) {
281 LOGVAL(VE_KEY_DUP, line, key->name);
282 return EXIT_FAILURE;
283 }
284 }
Radek Krejci345ad742015-06-03 11:04:18 +0200285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200286 /* key is a leaf */
287 if (key->nodetype != LY_NODE_LEAF) {
288 LOGVAL(VE_KEY_NLEAF, line, key->name);
289 return EXIT_FAILURE;
290 }
Radek Krejci345ad742015-06-03 11:04:18 +0200291
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200292 /* type of the leaf is not built-in empty */
293 if (key->type.base == LY_TYPE_EMPTY) {
294 LOGVAL(VE_KEY_TYPE, line, key->name);
295 return EXIT_FAILURE;
296 }
Radek Krejci345ad742015-06-03 11:04:18 +0200297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200298 /* config attribute is the same as of the list */
299 if ((flags & LY_NODE_CONFIG_MASK) != (key->flags & LY_NODE_CONFIG_MASK)) {
300 LOGVAL(VE_KEY_CONFIG, line, key->name);
301 return EXIT_FAILURE;
302 }
Radek Krejci345ad742015-06-03 11:04:18 +0200303
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200304 return EXIT_SUCCESS;
Radek Krejci345ad742015-06-03 11:04:18 +0200305}
306
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200307static int
308check_default(struct ly_type *type, const char *value)
Radek Krejcieac35532015-05-31 19:09:15 +0200309{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200310 /* TODO - RFC 6020, sec. 7.3.4 */
311 (void)type;
312 (void)value;
313 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +0200314}
315
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200316static int
317check_date(const char *date, unsigned int line)
Radek Krejcice7fb782015-05-29 16:52:34 +0200318{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200319 int i;
Radek Krejcice7fb782015-05-29 16:52:34 +0200320
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200321 assert(date);
Radek Krejcice7fb782015-05-29 16:52:34 +0200322
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200323 if (strlen(date) != LY_REV_SIZE - 1) {
324 goto error;
325 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200326
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200327 for (i = 0; i < LY_REV_SIZE - 1; i++) {
328 if (i == 4 || i == 7) {
329 if (date[i] != '-') {
330 goto error;
331 }
332 } else if (!isdigit(date[i])) {
333 goto error;
334 }
335 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200336
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200337 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +0200338
339error:
340
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200341 LOGVAL(VE_INDATE, line, date);
342 return EXIT_FAILURE;
Radek Krejcice7fb782015-05-29 16:52:34 +0200343}
344
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200345static const char *
346read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +0200347{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200348 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200349
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200350 /* there should be <text> child */
351 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
352 LOGWRN("Expected \"%s\" element in \"%s\" element.", name, node->name);
353 } else if (node->child->content) {
354 len = strlen(node->child->content);
355 return lydict_insert(ctx, node->child->content, len);
356 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200358 LOGVAL(VE_INARG, LOGLINE(node), name, node->name);
359 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200360}
361
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200362static struct ly_tpdf *
363find_superior_type(const char *name, struct ly_module *module, struct ly_mnode *parent)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200364{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200365 int i, j, found = 0;
366 int prefix_len = 0;
367 const char *qname;
368 struct ly_tpdf *tpdf;
369 int tpdf_size;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200370
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200371 qname = strchr(name, ':');
Radek Krejcida04f4a2015-05-21 12:54:09 +0200372
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200373 if (!qname) {
374 /* no prefix, try built-in types */
375 for (i = 1; i < LY_DATA_TYPE_COUNT; i++) {
376 if (!strcmp(ly_types[i].def->name, name)) {
377 return ly_types[i].def;
378 }
379 }
380 qname = name;
381 } else {
382 /* set qname to correct position after colon */
383 prefix_len = qname - name;
384 qname++;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200385
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200386 if (!strncmp(name, module->prefix, prefix_len) && !module->prefix[prefix_len]) {
387 /* prefix refers to the current module, ignore it */
388 prefix_len = 0;
389 }
390 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200391
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200392 if (!prefix_len && parent) {
393 /* search in local typedefs */
394 while (parent) {
395 switch (parent->nodetype) {
396 case LY_NODE_CONTAINER:
397 tpdf_size = ((struct ly_mnode_container *)parent)->tpdf_size;
398 tpdf = ((struct ly_mnode_container *)parent)->tpdf;
399 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200401 case LY_NODE_LIST:
402 tpdf_size = ((struct ly_mnode_list *)parent)->tpdf_size;
403 tpdf = ((struct ly_mnode_list *)parent)->tpdf;
404 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200405
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200406 case LY_NODE_GROUPING:
407 tpdf_size = ((struct ly_mnode_grp *)parent)->tpdf_size;
408 tpdf = ((struct ly_mnode_grp *)parent)->tpdf;
409 break;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200410
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200411 default:
412 parent = parent->parent;
413 continue;
414 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200415
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200416 for (i = 0; i < tpdf_size; i++) {
417 if (!strcmp(tpdf[i].name, qname)) {
418 return &tpdf[i];
419 }
420 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200421
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200422 parent = parent->parent;
423 }
424 } else if (prefix_len) {
425 /* get module where to search */
426 for (i = 0; i < module->imp_size; i++) {
427 if (!strncmp(module->imp[i].prefix, name, prefix_len) && !module->imp[i].prefix[prefix_len]) {
428 module = module->imp[i].module;
429 found = 1;
430 break;
431 }
432 }
433 if (!found) {
434 return NULL;
435 }
436 }
437
438 /* search in top level typedefs */
439 for (i = 0; i < module->tpdf_size; i++) {
440 if (!strcmp(module->tpdf[i].name, qname)) {
441 return &module->tpdf[i];
442 }
443 }
444
445 /* search in submodules */
446 for (i = 0; i < module->inc_size; i++) {
447 for (j = 0; j < module->inc[i].submodule->tpdf_size; j++) {
448 if (!strcmp(module->inc[i].submodule->tpdf[j].name, qname)) {
449 return &module->inc[i].submodule->tpdf[j];
450 }
451 }
452 }
453
454 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +0200455}
456
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200457static struct ly_ident *
458find_base_ident_sub(struct ly_module *module, struct ly_ident *ident, const char *basename)
Radek Krejciefaeba32015-05-27 14:30:57 +0200459{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200460 unsigned int i;
461 struct ly_ident *base_iter;
462 struct ly_ident_der *der;
Radek Krejciefaeba32015-05-27 14:30:57 +0200463
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200464 for (i = 0; i < module->ident_size; i++) {
465 if (!strcmp(basename, module->ident[i].name)) {
466 /* we are done */
Radek Krejciefaeba32015-05-27 14:30:57 +0200467
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200468 if (!ident) {
469 /* just search for type, so do not modify anything, just return
470 * the base identity pointer
471 */
472 return &module->ident[i];
473 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200474
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200475 /* we are resolving identity definition, so now update structures */
476 ident->base = base_iter = &module->ident[i];
Radek Krejciefaeba32015-05-27 14:30:57 +0200477
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200478 while (base_iter) {
479 for (der = base_iter->der; der && der->next; der = der->next);
480 if (der) {
481 der->next = malloc(sizeof *der);
482 der = der->next;
483 } else {
484 ident->base->der = der = malloc(sizeof *der);
485 }
486 der->next = NULL;
487 der->ident = ident;
Radek Krejciefaeba32015-05-27 14:30:57 +0200488
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200489 base_iter = base_iter->base;
490 }
491 return ident->base;
492 }
493 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200494
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200495 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200496}
497
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200498static struct ly_ident *
499find_base_ident(struct ly_module *module, struct ly_ident *ident, struct lyxml_elem *node)
Radek Krejci04581c62015-05-22 21:24:00 +0200500{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200501 const char *name;
502 int prefix_len = 0;
503 int i, found = 0;
504 struct ly_ident *result;
505 const char *basename;
Radek Krejci04581c62015-05-22 21:24:00 +0200506
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200507 basename = lyxml_get_attr(node, "name", NULL);
508 if (!basename) {
509 LOGVAL(VE_MISSARG, LOGLINE(node), "name", "base");
510 return NULL;
511 }
Radek Krejci04581c62015-05-22 21:24:00 +0200512
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200513 /* search for the base identity */
514 name = strchr(basename, ':');
515 if (name) {
516 /* set name to correct position after colon */
517 prefix_len = name - basename;
518 name++;
Radek Krejci04581c62015-05-22 21:24:00 +0200519
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200520 if (!strncmp(basename, module->prefix, prefix_len) && !module->prefix[prefix_len]) {
521 /* prefix refers to the current module, ignore it */
522 prefix_len = 0;
523 }
524 } else {
525 name = basename;
526 }
Radek Krejci04581c62015-05-22 21:24:00 +0200527
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200528 if (prefix_len) {
529 /* get module where to search */
530 for (i = 0; i < module->imp_size; i++) {
531 if (!strncmp(module->imp[i].prefix, basename, prefix_len)
532 && !module->imp[i].prefix[prefix_len]) {
533 module = module->imp[i].module;
534 found = 1;
535 break;
536 }
537 }
538 if (!found) {
539 /* identity refers unknown data model */
540 LOGVAL(VE_INPREFIX, LOGLINE(node), basename);
541 return NULL;
542 }
543 } else {
544 /* search in submodules */
545 for (i = 0; i < module->inc_size; i++) {
546 result = find_base_ident_sub((struct ly_module *)module->inc[i].submodule, ident, name);
547 if (result) {
548 return result;
549 }
550 }
551 }
Radek Krejci04581c62015-05-22 21:24:00 +0200552
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200553 /* search in the identified module */
554 result = find_base_ident_sub(module, ident, name);
555 if (!result) {
556 LOGVAL(VE_INARG, LOGLINE(node), basename, ident ? "identity" : "type");
557 }
Radek Krejciefaeba32015-05-27 14:30:57 +0200558
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200559 return result;
Radek Krejci04581c62015-05-22 21:24:00 +0200560}
561
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200562static int
563fill_yin_identity(struct ly_module *module, struct lyxml_elem *yin, struct ly_ident *ident)
Radek Krejci04581c62015-05-22 21:24:00 +0200564{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200565 struct lyxml_elem *node, *next;
Radek Krejci04581c62015-05-22 21:24:00 +0200566
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200567 if (read_yin_common(module, NULL, (struct ly_mnode *)ident, yin, OPT_IDENT | OPT_MODULE)) {
568 return EXIT_FAILURE;
569 }
Radek Krejci04581c62015-05-22 21:24:00 +0200570
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200571 LY_TREE_FOR_SAFE(yin->child, next, node) {
572 if (!strcmp(node->name, "base")) {
573 if (ident->base) {
574 LOGVAL(VE_TOOMANY, LOGLINE(node), "base", "identity");
575 return EXIT_FAILURE;
576 }
577 if (!find_base_ident(module, ident, node)) {
578 return EXIT_FAILURE;
579 }
580 } else {
581 LOGVAL(VE_INSTMT, LOGLINE(node), node->name, "identity");
582 return EXIT_FAILURE;
583 }
Radek Krejci04581c62015-05-22 21:24:00 +0200584
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200585 lyxml_free_elem(module->ctx, node);
586 }
Radek Krejci04581c62015-05-22 21:24:00 +0200587
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200588 return EXIT_SUCCESS;
Radek Krejci04581c62015-05-22 21:24:00 +0200589}
590
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200591static int
592fill_yin_type(struct ly_module *module, struct ly_mnode *parent, struct lyxml_elem *yin, struct ly_type *type)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200593{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200594 const char *value, *delim;
595 struct lyxml_elem *next, *node, root;
596 int i, j, r;
597 int64_t v, v_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200598
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200599 /* init */
600 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +0200601
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200602 GETVAL(value, yin, "name")
603 delim = strchr(value, ':');
604 if (delim) {
605 type->prefix = lydict_insert(module->ctx, value, delim - value);
606 }
Radek Krejci667b97f2015-05-25 15:03:30 +0200607
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200608 type->der = find_superior_type(value, module, parent);
609 if (!type->der) {
610 LOGVAL(VE_INARG, LOGLINE(yin), value, yin->name);
611 goto error;
612 }
613 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200614
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200615 switch (type->base) {
616 case LY_TYPE_BINARY:
617 /* TODO length, 9.4.4
618 * - optional, 0..1, rekurzivni - omezuje, string (podobne jako range),
619 * hodnoty se musi vejit do 64b, podelementy
620 */
621 break;
Radek Krejci04581c62015-05-22 21:24:00 +0200622
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200623 case LY_TYPE_BITS:
624 /* TODO bit, 9.7.4
625 * 1..n, nerekurzivni, stringy s podelementy */
626 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200627
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200628 case LY_TYPE_DEC64:
629 /* TODO fraction-digits, 9.3.4
630 * - MUST, 1, nerekurzivni, hodnota 1-18 */
631 /* TODO range, 9.2.4
632 * - optional, 0..1, rekurzivne - omezuje, string, podelementy*/
633 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200634
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200635 case LY_TYPE_ENUM:
636 /* RFC 6020 9.6 */
Radek Krejci25d782a2015-05-22 15:03:23 +0200637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200638 /* get enum specification, at least one must be present */
639 LY_TREE_FOR_SAFE(yin->child, next, node) {
640 if (!strcmp(node->name, "enum")) {
641 lyxml_unlink_elem(node);
642 lyxml_add_child(&root, node);
643 type->info.enums.count++;
644 }
645 }
646 if (yin->child) {
647 LOGVAL(VE_INSTMT, LOGLINE(yin->child), yin->child->name);
648 goto error;
649 }
650 if (!type->info.enums.count) {
651 if (type->der->type.der) {
652 /* this is just a derived type with no enum specified */
653 break;
654 }
655 LOGVAL(VE_MISSSTMT2, LOGLINE(yin), "enum", "type");
656 goto error;
657 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200658
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200659 type->info.enums.list = calloc(type->info.enums.count, sizeof *type->info.enums.list);
660 for (i = v = 0; root.child; i++) {
661 r = read_yin_common(module, NULL, (struct ly_mnode *)&type->info.enums.list[i], root.child, OPT_IDENT);
662 if (r) {
663 type->info.enums.count = i + 1;
664 goto error;
665 }
666 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
667 value = type->info.enums.list[i].name;
668 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
669 LOGVAL(VE_ENUM_WS, LOGLINE(root.child), value);
670 type->info.enums.count = i + 1;
671 goto error;
672 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200673
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200674 /* check the name uniqueness */
675 for (j = 0; j < i; j++) {
676 if (!strcmp(type->info.enums.list[j].name, type->info.enums.list[i].name)) {
677 LOGVAL(VE_ENUM_DUPNAME, LOGLINE(root.child), type->info.enums.list[i].name);
678 type->info.enums.count = i + 1;
679 goto error;
680 }
681 }
Radek Krejci04581c62015-05-22 21:24:00 +0200682
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200683 node = root.child->child;
684 if (node && !strcmp(node->name, "value")) {
685 value = lyxml_get_attr(node, "value", NULL);
686 v_ = strtol(value, NULL, 10);
Radek Krejcida04f4a2015-05-21 12:54:09 +0200687
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200688 /* range check */
689 if (v_ < INT32_MIN || v_ > INT32_MAX) {
690 LOGVAL(VE_INARG, LOGLINE(node), value, "enum/value");
691 type->info.enums.count = i + 1;
692 goto error;
693 }
694 type->info.enums.list[i].value = v_;
695
696 /* keep the highest enum value for automatic increment */
697 if (type->info.enums.list[i].value > v) {
698 v = type->info.enums.list[i].value;
699 v++;
700 } else {
701 /* check that the value is unique */
702 for (j = 0; j < i; j++) {
703 if (type->info.enums.list[j].value == type->info.enums.list[i].value) {
704 LOGVAL(VE_ENUM_DUPVAL, LOGLINE(node), type->info.enums.list[i].value,
705 type->info.enums.list[i].name);
706 type->info.enums.count = i + 1;
707 goto error;
708 }
709 }
710 }
711 } else {
712 /* assign value automatically */
713 if (v > INT32_MAX) {
714 LOGVAL(VE_INARG, LOGLINE(root.child), "2147483648", "enum/value");
715 type->info.enums.count = i + 1;
716 goto error;
717 }
718 type->info.enums.list[i].value = v;
719 v++;
720 }
721 lyxml_free_elem(module->ctx, root.child);
722 }
723 break;
724
725 case LY_TYPE_IDENT:
726 /* RFC 6020 9.10 */
727
728 /* get base specification, exactly one must be present */
729 if (!yin->child) {
730 LOGVAL(VE_MISSSTMT2, LOGLINE(yin), "base", "type");
731 goto error;
732 }
733 if (strcmp(yin->child->name, "base")) {
734 LOGVAL(VE_INSTMT, LOGLINE(yin->child), yin->child->name);
735 goto error;
736 }
737 if (yin->child->next) {
738 LOGVAL(VE_INSTMT, LOGLINE(yin->child->next), yin->child->next->name);
739 goto error;
740 }
741 type->info.ident.ref = find_base_ident(module, NULL, yin->child);
742 if (!type->info.ident.ref) {
743 return EXIT_FAILURE;
744 }
745 break;
746
747 case LY_TYPE_INST:
748 /* TODO require-instance, 9.13.2
749 * - 0..1, true/false */
750 break;
751
752 case LY_TYPE_INT8:
753 case LY_TYPE_INT16:
754 case LY_TYPE_INT32:
755 case LY_TYPE_INT64:
756 case LY_TYPE_UINT8:
757 case LY_TYPE_UINT16:
758 case LY_TYPE_UINT32:
759 case LY_TYPE_UINT64:
760 /* TODO range, 9.2.4
761 * - optional, 0..1, i rekurzivne - omezuje, string, podelementy*/
762 break;
763
764 case LY_TYPE_LEAFREF:
765 /* TODO path, 9.9.2
766 * - 1, nerekurzivni, string */
767 break;
768
769 case LY_TYPE_STRING:
770 /* TODO length, 9.4.4
771 * - optional, 0..1, rekurzivni - omezuje, string (podobne jako range), hodnoty se musi vejit do 64b, podelementy
772 * pattern, 9.4.6
773 * - optional, 0..n, rekurzivni - rozsiruje, string, podelementy */
774 break;
775
776 case LY_TYPE_UNION:
777 /* TODO type, 7.4
778 * - 1..n, nerekurzivni, resp rekurzivni pro union ale bez vazby na predky, nesmi byt empty nebo leafref */
779 break;
780
781 default:
782 /* nothing needed :
783 * LY_TYPE_BOOL, LY_TYPE_EMPTY
784 */
785 break;
786 }
787
788 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +0200789
790error:
791
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200792 LY_TREE_FOR_SAFE(root.child, next, node) {
793 lyxml_free_elem(module->ctx, node);
794 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200795
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200796 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200797}
798
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200799static int
800fill_yin_typedef(struct ly_module *module, struct ly_mnode *parent, struct lyxml_elem *yin, struct ly_tpdf *tpdf)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200801{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200802 const char *value;
803 struct lyxml_elem *node, *next;
804 int r = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200805
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200806 GETVAL(value, yin, "name");
807 if (check_identifier(value, LY_IDENT_TYPE, LOGLINE(yin), module, parent)) {
808 goto error;
809 }
810 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +0200811
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200812 /* generic part - status, description, reference */
813 if (read_yin_common(module, NULL, (struct ly_mnode *)tpdf, yin, OPT_IDENT)) {
814 goto error;
815 }
Radek Krejcieac35532015-05-31 19:09:15 +0200816
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200817 LY_TREE_FOR_SAFE(yin->child, next, node) {
818 if (!strcmp(node->name, "type")) {
819 if (tpdf->type.der) {
820 LOGVAL(VE_TOOMANY, LOGLINE(node), node->name, yin->name);
821 goto error;
822 }
823 r = fill_yin_type(module, parent, node, &tpdf->type);
824 } else if (!strcmp(node->name, "default")) {
825 if (tpdf->dflt) {
826 LOGVAL(VE_TOOMANY, LOGLINE(node), node->name, yin->name);
827 goto error;
828 }
829 GETVAL(value, node, "value");
830 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
831 } else if (!strcmp(node->name, "units")) {
832 if (tpdf->units) {
833 LOGVAL(VE_TOOMANY, LOGLINE(node), node->name, yin->name);
834 goto error;
835 }
836 GETVAL(value, node, "name");
837 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
838 } else {
839 LOGVAL(VE_INSTMT, LOGLINE(node), value);
840 r = 1;
841 }
842 lyxml_free_elem(module->ctx, node);
843 if (r) {
844 goto error;
845 }
846 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200847
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200848 /* check mandatory value */
849 if (!tpdf->type.der) {
850 LOGVAL(VE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
851 goto error;
852 }
Radek Krejcieac35532015-05-31 19:09:15 +0200853
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200854 /* check default value */
855 if (check_default(&tpdf->type, tpdf->dflt)) {
856 goto error;
857 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200858
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200859 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +0200860
861error:
862
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200863 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200864}
865
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200866static int
867fill_yin_must(struct ly_module *module, struct lyxml_elem *yin, struct ly_must *must)
Radek Krejci800af702015-06-02 13:46:01 +0200868{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200869 struct lyxml_elem *child, *next;
870 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +0200871
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200872 GETVAL(value, yin, "condition");
873 must->cond = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +0200874
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200875 LY_TREE_FOR_SAFE(yin->child, next, child) {
876 if (!strcmp(child->name, "description")) {
877 if (must->dsc) {
878 LOGVAL(VE_TOOMANY, LOGLINE(child), child->name, yin->name);
879 goto error;
880 }
881 must->dsc = read_yin_subnode(module->ctx, child, "text");
882 if (!must->dsc) {
883 goto error;
884 }
885 } else if (!strcmp(child->name, "reference")) {
886 if (must->ref) {
887 LOGVAL(VE_TOOMANY, LOGLINE(child), child->name, yin->name);
888 goto error;
889 }
890 must->ref = read_yin_subnode(module->ctx, child, "text");
891 if (!must->ref) {
892 goto error;
893 }
894 } else if (!strcmp(child->name, "error-app-tag")) {
895 if (must->eapptag) {
896 LOGVAL(VE_TOOMANY, LOGLINE(child), child->name, yin->name);
897 goto error;
898 }
899 must->eapptag = read_yin_subnode(module->ctx, child, "value");
900 if (!must->eapptag) {
901 goto error;
902 }
903 } else if (!strcmp(child->name, "error-message")) {
904 if (must->emsg) {
905 LOGVAL(VE_TOOMANY, LOGLINE(child), child->name, yin->name);
906 goto error;
907 }
908 must->emsg = read_yin_subnode(module->ctx, child, "value");
909 if (!must->emsg) {
910 goto error;
911 }
912 } else {
913 LOGVAL(VE_INSTMT, LOGLINE(child), child->name);
914 goto error;
915 }
Radek Krejci800af702015-06-02 13:46:01 +0200916
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200917 lyxml_free_elem(module->ctx, child);
918 }
Radek Krejci800af702015-06-02 13:46:01 +0200919
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200920 return EXIT_SUCCESS;
Radek Krejci800af702015-06-02 13:46:01 +0200921
922error:
923
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200924 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +0200925}
926
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200927static int
928fill_yin_augment(struct ly_module *module, struct ly_mnode *parent, struct lyxml_elem *yin, struct ly_augment *aug)
Radek Krejci106efc02015-06-10 14:36:27 +0200929{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200930 const char *value;
Radek Krejci106efc02015-06-10 14:36:27 +0200931
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200932 GETVAL(value, yin, "target-node");
933 aug->target_name = lydict_insert(module->ctx, value, 0);
934 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +0200935
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200936 /* do not resolve now, just keep the definition which will be parsed later
937 * when we will have the target node
938 */
939 lyxml_unlink_elem(yin);
940 aug->child = (struct ly_mnode *)yin;
Radek Krejci106efc02015-06-10 14:36:27 +0200941
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200942 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +0200943
944error:
945
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200946 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +0200947}
948
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200949static int
950fill_yin_refine(struct ly_module *module, struct lyxml_elem *yin, struct ly_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +0200951{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200952 struct lyxml_elem *sub, *next;
953 const char *value;
954 char *endptr;
955 int f_mand = 0, f_min = 0, f_max = 0;
956 int c_must = 0;
957 int r;
958 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +0200959
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200960 GETVAL(value, yin, "target-node");
961 rfn->target = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci3bde87f2015-06-05 16:51:58 +0200962
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200963 if (read_yin_common(module, NULL, (struct ly_mnode *)rfn, yin, OPT_CONFIG)) {
964 goto error;
965 }
Radek Krejci3bde87f2015-06-05 16:51:58 +0200966
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200967 LY_TREE_FOR_SAFE(yin->child, next, sub) {
968 /* limited applicability */
969 if (!strcmp(sub->name, "default")) {
970 /* leaf or choice */
971 if (rfn->mod.dflt) {
972 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
973 goto error;
974 }
Radek Krejci3bde87f2015-06-05 16:51:58 +0200975
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200976 /* check possibility of statements combination */
977 if (rfn->target_type) {
978 rfn->target_type &= (LY_NODE_LEAF | LY_NODE_CHOICE);
979 if (!rfn->target_type) {
980 LOGVAL(VE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
981 goto error;
982 }
983 } else {
984 rfn->target_type = LY_NODE_LEAF | LY_NODE_CHOICE;
985 }
Radek Krejci3bde87f2015-06-05 16:51:58 +0200986
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200987 GETVAL(value, sub, "value");
988 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
989 } else if (!strcmp(sub->name, "mandatory")) {
990 /* leaf, choice or anyxml */
991 if (f_mand) {
992 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
993 goto error;
994 }
995 /* just checking the flags in leaf is not sufficient, we would allow
996 * multiple mandatory statements with the "false" value
997 */
998 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +0200999
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001000 /* check possibility of statements combination */
1001 if (rfn->target_type) {
1002 rfn->target_type &= (LY_NODE_LEAF | LY_NODE_CHOICE | LY_NODE_ANYXML);
1003 if (!rfn->target_type) {
1004 LOGVAL(VE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
1005 goto error;
1006 }
1007 } else {
1008 rfn->target_type = LY_NODE_LEAF | LY_NODE_CHOICE | LY_NODE_ANYXML;
1009 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02001010
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001011 GETVAL(value, sub, "value");
1012 if (!strcmp(value, "true")) {
1013 rfn->flags |= LY_NODE_MAND_TRUE;
1014 } else if (!strcmp(value, "false")) {
1015 rfn->flags |= LY_NODE_MAND_FALSE;
1016 } else {
1017 LOGVAL(VE_INARG, LOGLINE(sub), value, sub->name);
1018 goto error;
1019 }
1020 } else if (!strcmp(sub->name, "min-elements")) {
1021 /* list or leaf-list */
1022 if (f_min) {
1023 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
1024 goto error;
1025 }
1026 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02001027
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001028 /* check possibility of statements combination */
1029 if (rfn->target_type) {
1030 rfn->target_type &= (LY_NODE_LIST | LY_NODE_LEAFLIST);
1031 if (!rfn->target_type) {
1032 LOGVAL(VE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
1033 goto error;
1034 }
1035 } else {
1036 rfn->target_type = LY_NODE_LIST | LY_NODE_LEAFLIST;
1037 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02001038
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001039 GETVAL(value, sub, "value");
1040 while (isspace(value[0])) {
1041 value++;
1042 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02001043
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001044 /* convert it to uint32_t */
1045 errno = 0;
1046 endptr = NULL;
1047 val = strtoul(value, &endptr, 10);
1048 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
1049 LOGVAL(VE_INARG, LOGLINE(sub), value, sub->name);
1050 goto error;
1051 }
1052 rfn->mod.list.min = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02001053
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001054 /* magic - bit 3 in flags means min set */
1055 rfn->flags |= 0x04;
1056 } else if (!strcmp(sub->name, "max-elements")) {
1057 /* list or leaf-list */
1058 if (f_max) {
1059 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
1060 goto error;
1061 }
1062 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02001063
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001064 /* check possibility of statements combination */
1065 if (rfn->target_type) {
1066 rfn->target_type &= (LY_NODE_LIST | LY_NODE_LEAFLIST);
1067 if (!rfn->target_type) {
1068 LOGVAL(VE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
1069 goto error;
1070 }
1071 } else {
1072 rfn->target_type = LY_NODE_LIST | LY_NODE_LEAFLIST;
1073 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02001074
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001075 GETVAL(value, sub, "value");
1076 while (isspace(value[0])) {
1077 value++;
1078 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02001079
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001080 /* convert it to uint32_t */
1081 errno = 0;
1082 endptr = NULL;
1083 val = strtoul(value, &endptr, 10);
1084 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
1085 LOGVAL(VE_INARG, LOGLINE(sub), value, sub->name);
1086 goto error;
1087 }
1088 rfn->mod.list.max = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02001089
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001090 /* magic - bit 4 in flags means min set */
1091 rfn->flags |= 0x08;
1092 } else if (!strcmp(sub->name, "presence")) {
1093 /* container */
1094 if (rfn->mod.presence) {
1095 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
1096 goto error;
1097 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02001098
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001099 /* check possibility of statements combination */
1100 if (rfn->target_type) {
1101 rfn->target_type &= LY_NODE_CONTAINER;
1102 if (!rfn->target_type) {
1103 LOGVAL(VE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
1104 goto error;
1105 }
1106 } else {
1107 rfn->target_type = LY_NODE_CONTAINER;
1108 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02001109
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001110 GETVAL(value, sub, "value");
1111 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
1112 } else if (!strcmp(sub->name, "must")) {
1113 /* leaf-list, list, container or anyxml */
1114 /* check possibility of statements combination */
1115 if (rfn->target_type) {
1116 rfn->target_type &= (LY_NODE_LIST | LY_NODE_LEAFLIST | LY_NODE_CONTAINER | LY_NODE_ANYXML);
1117 if (!rfn->target_type) {
1118 LOGVAL(VE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
1119 goto error;
1120 }
1121 } else {
1122 rfn->target_type = LY_NODE_LIST | LY_NODE_LEAFLIST | LY_NODE_CONTAINER | LY_NODE_ANYXML;
1123 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02001124
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001125 c_must++;
Radek Krejci3bde87f2015-06-05 16:51:58 +02001126
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001127 } else {
1128 LOGVAL(VE_INSTMT, LOGLINE(sub), sub->name);
1129 goto error;
1130 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02001131
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001132 lyxml_free_elem(module->ctx, sub);
1133 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02001134
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001135 /* process nodes with cardinality of 0..n */
1136 if (c_must) {
1137 rfn->must = calloc(c_must, sizeof *rfn->must);
1138 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02001139
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001140 LY_TREE_FOR_SAFE(yin->child, next, sub) {
1141 if (!strcmp(sub->name, "must")) {
1142 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
1143 rfn->must_size++;
Radek Krejci3bde87f2015-06-05 16:51:58 +02001144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001145 if (r) {
1146 goto error;
1147 }
1148 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02001149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001150 lyxml_free_elem(module->ctx, sub);
1151 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02001152
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001153 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02001154
1155error:
1156
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001157 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02001158}
1159
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001160static int
1161fill_yin_import(struct ly_module *module, struct lyxml_elem *yin, struct ly_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02001162{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001163 struct lyxml_elem *child;
1164 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02001165
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001166 LY_TREE_FOR(yin->child, child) {
1167 if (!strcmp(child->name, "prefix")) {
1168 GETVAL(value, child, "value");
1169 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
1170 goto error;
1171 }
1172 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
1173 } else if (!strcmp(child->name, "revision-date")) {
1174 if (imp->rev[0]) {
1175 LOGVAL(VE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
1176 goto error;
1177 }
1178 GETVAL(value, child, "date");
1179 if (check_date(value, LOGLINE(child))) {
1180 goto error;
1181 }
1182 memcpy(imp->rev, value, LY_REV_SIZE - 1);
1183 } else {
1184 LOGVAL(VE_INSTMT, LOGLINE(child), child->name);
1185 goto error;
1186 }
1187 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001188
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001189 /* check mandatory information */
1190 if (!imp->prefix) {
1191 LOGVAL(VE_MISSSTMT2, LOGLINE(yin), "prefix", yin->name);
1192 goto error;
1193 }
Radek Krejcice7fb782015-05-29 16:52:34 +02001194
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001195 GETVAL(value, yin, "module");
1196 imp->module = ly_ctx_get_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL, 1);
1197 if (!imp->module) {
1198 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
1199 LOGVAL(VE_INARG, LOGLINE(yin), value, yin->name);
1200 goto error;
1201 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001202
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001203 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02001204
1205error:
1206
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001207 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02001208}
1209
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001210static int
1211fill_yin_include(struct ly_module *module, struct lyxml_elem *yin, struct ly_include *inc)
Radek Krejciefaeba32015-05-27 14:30:57 +02001212{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001213 struct lyxml_elem *child;
1214 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02001215
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001216 LY_TREE_FOR(yin->child, child) {
1217 if (!strcmp(child->name, "revision-date")) {
1218 if (inc->rev[0]) {
1219 LOGVAL(VE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
1220 goto error;
1221 }
1222 GETVAL(value, child, "date");
1223 if (check_date(value, LOGLINE(child))) {
1224 goto error;
1225 }
1226 memcpy(inc->rev, value, LY_REV_SIZE - 1);
1227 } else {
1228 LOGVAL(VE_INSTMT, LOGLINE(child), child->name);
1229 goto error;
1230 }
1231 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001232
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001233 GETVAL(value, yin, "module");
1234 inc->submodule = ly_ctx_get_submodule(module, value, inc->rev[0] ? inc->rev : NULL);
1235 if (!inc->submodule) {
1236 LOGERR(LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
1237 LOGVAL(VE_INARG, LOGLINE(yin), value, yin->name);
1238 goto error;
1239 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001240
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001241 /* check that belongs-to corresponds */
1242 if (module->type) {
1243 module = ((struct ly_submodule *)module)->belongsto;
1244 }
1245 if (inc->submodule->belongsto != module) {
1246 LOGVAL(VE_INARG, LOGLINE(yin), value, yin->name);
1247 LOGVAL(VE_SPEC, 0, "The included module does not belongs-to the \"%s\" module", module->name);
1248 goto error;
1249 }
Radek Krejciefaeba32015-05-27 14:30:57 +02001250
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001251 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02001252
1253error:
1254
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001255 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02001256}
1257
Radek Krejcida04f4a2015-05-21 12:54:09 +02001258/*
1259 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02001260 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02001261 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02001262 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001263static int
1264read_yin_common(struct ly_module *module, struct ly_mnode *parent,
1265 struct ly_mnode *mnode, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001266{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001267 const char *value;
1268 struct lyxml_elem *sub, *next;
1269 struct ly_ctx *const ctx = module->ctx;
1270 int r = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001271
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001272 if (opt & OPT_MODULE) {
1273 mnode->module = module;
1274 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001275
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001276 if (opt & OPT_IDENT) {
1277 GETVAL(value, xmlnode, "name");
1278 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(xmlnode), NULL, NULL)) {
1279 goto error;
1280 }
1281 mnode->name = lydict_insert(ctx, value, strlen(value));
1282 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001283
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001284 /* process local parameters */
1285 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
1286 if (!strcmp(sub->name, "description")) {
1287 if (mnode->dsc) {
1288 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
1289 goto error;
1290 }
1291 mnode->dsc = read_yin_subnode(ctx, sub, "text");
1292 if (!mnode->dsc) {
1293 r = 1;
1294 }
1295 } else if (!strcmp(sub->name, "reference")) {
1296 if (mnode->ref) {
1297 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
1298 goto error;
1299 }
1300 mnode->ref = read_yin_subnode(ctx, sub, "text");
1301 if (!mnode->ref) {
1302 r = 1;
1303 }
1304 } else if (!strcmp(sub->name, "status")) {
1305 if (mnode->flags & LY_NODE_STATUS_MASK) {
1306 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
1307 goto error;
1308 }
1309 GETVAL(value, sub, "value");
1310 if (!strcmp(value, "current")) {
1311 mnode->flags |= LY_NODE_STATUS_CURR;
1312 } else if (!strcmp(value, "deprecated")) {
1313 mnode->flags |= LY_NODE_STATUS_DEPRC;
1314 } else if (!strcmp(value, "obsolete")) {
1315 mnode->flags |= LY_NODE_STATUS_OBSLT;
1316 } else {
1317 LOGVAL(VE_INARG, LOGLINE(sub), value, sub->name);
1318 r = 1;
1319 }
1320 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
1321 if (mnode->flags & LY_NODE_CONFIG_MASK) {
1322 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
1323 goto error;
1324 }
1325 GETVAL(value, sub, "value");
1326 if (!strcmp(value, "false")) {
1327 mnode->flags |= LY_NODE_CONFIG_R;
1328 } else if (!strcmp(value, "true")) {
1329 mnode->flags |= LY_NODE_CONFIG_W;
1330 } else {
1331 LOGVAL(VE_INARG, LOGLINE(sub), value, sub->name);
1332 r = 1;
1333 }
1334 } else {
1335 /* skip the lyxml_free_elem */
1336 continue;
1337 }
1338 lyxml_free_elem(ctx, sub);
1339 if (r) {
1340 goto error;
1341 }
1342 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001343
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001344 if ((opt & OPT_INHERIT) && !(mnode->flags & LY_NODE_CONFIG_MASK)) {
1345 /* get config flag from parent */
1346 if (parent) {
1347 mnode->flags |= parent->flags & LY_NODE_CONFIG_MASK;
1348 } else {
1349 /* default config is true */
1350 mnode->flags |= LY_NODE_CONFIG_W;
1351 }
1352 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001353
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001354 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001355
1356error:
1357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001358 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001359}
1360
Radek Krejcib4cf2022015-06-03 14:40:05 +02001361/* additional check in case statement - the child must be unique across
1362 * all other case names and its data children
1363 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001364static int
1365check_branch_id(struct ly_mnode *parent, struct ly_mnode *new, struct ly_mnode *excl, int line)
Radek Krejcib4cf2022015-06-03 14:40:05 +02001366{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001367 struct ly_mnode *mnode, *submnode;
Radek Krejcib4cf2022015-06-03 14:40:05 +02001368
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001369 if (new->nodetype == LY_NODE_CHOICE) {
1370 /* we have nested choice in case, so we need recursion */
1371 LY_TREE_FOR(new->child, mnode) {
1372 if (mnode->nodetype == LY_NODE_CASE) {
1373 LY_TREE_FOR(mnode->child, submnode) {
1374 if (check_branch_id(parent, submnode, new, line)) {
1375 return EXIT_FAILURE;
1376 }
1377 }
1378 } else if (check_branch_id(parent, mnode, new, line)) {
1379 return EXIT_FAILURE;
1380 }
1381 }
1382 } else {
1383 LY_TREE_FOR(parent->child, mnode) {
1384 if (mnode == excl) {
1385 continue;
1386 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02001387
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001388 if (!strcmp(new->name, mnode->name)) {
1389 LOGVAL(VE_INID, line, new->name, "duplicated identifier within a choice's cases");
1390 return EXIT_FAILURE;
1391 }
1392 if (mnode->nodetype == LY_NODE_CASE) {
1393 LY_TREE_FOR(mnode->child, submnode) {
1394 if (!strcmp(new->name, submnode->name)) {
1395 LOGVAL(VE_INID, line, new->name, "duplicated identifier within a choice's cases");
1396 return EXIT_FAILURE;
1397 }
1398 }
1399 }
1400 }
1401 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02001402
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001403 return EXIT_SUCCESS;
Radek Krejcib4cf2022015-06-03 14:40:05 +02001404}
1405
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001406static struct ly_mnode *
1407read_yin_case(struct ly_module *module,
1408 struct ly_mnode *parent, struct lyxml_elem *yin, int resolve, struct mnode_list **unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02001409{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001410 struct lyxml_elem *sub, *next;
1411 struct ly_mnode_case *mcase;
1412 struct ly_mnode *retval, *mnode = NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02001413
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001414 mcase = calloc(1, sizeof *mcase);
1415 mcase->nodetype = LY_NODE_CASE;
1416 mcase->prev = (struct ly_mnode *)mcase;
1417 retval = (struct ly_mnode *)mcase;
Radek Krejcib4cf2022015-06-03 14:40:05 +02001418
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001419 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT)) {
1420 goto error;
1421 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02001422
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001423 /* process choice's specific children */
1424 LY_TREE_FOR_SAFE(yin->child, next, sub) {
1425 if (!strcmp(sub->name, "container")) {
1426 mnode = read_yin_container(module, retval, sub, resolve, unres);
1427 } else if (!strcmp(sub->name, "leaf-list")) {
1428 mnode = read_yin_leaflist(module, retval, sub, resolve);
1429 } else if (!strcmp(sub->name, "leaf")) {
1430 mnode = read_yin_leaf(module, retval, sub, resolve);
1431 } else if (!strcmp(sub->name, "list")) {
1432 mnode = read_yin_list(module, retval, sub, resolve, unres);
1433 } else if (!strcmp(sub->name, "uses")) {
1434 mnode = read_yin_uses(module, retval, sub, resolve, unres);
1435 } else if (!strcmp(sub->name, "choice")) {
1436 mnode = read_yin_choice(module, retval, sub, resolve, unres);
1437 } else if (!strcmp(sub->name, "anyxml")) {
1438 mnode = read_yin_anyxml(module, retval, sub, resolve);
Radek Krejcib4cf2022015-06-03 14:40:05 +02001439#if 0
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001440 } else {
1441 LOGVAL(VE_INSTMT, LOGLINE(sub), sub->name);
1442 goto error;
Radek Krejci8eaf9bd2015-06-04 11:05:18 +02001443#else
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001444 } else {
1445 continue;
Radek Krejcib4cf2022015-06-03 14:40:05 +02001446#endif
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001447 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02001448
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001449 if (!mnode) {
1450 goto error;
1451 } else if (check_branch_id(parent, mnode, mnode, LOGLINE(sub))) {
1452 goto error;
1453 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02001454
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001455 mnode = NULL;
1456 lyxml_free_elem(module->ctx, sub);
1457 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02001458
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001459 /* inherit config flag */
1460 if (parent) {
1461 retval->flags |= parent->flags & LY_NODE_CONFIG_MASK;
1462 } else {
1463 /* default config is true */
1464 retval->flags |= LY_NODE_CONFIG_W;
1465 }
Radek Krejcib388c152015-06-04 17:03:03 +02001466
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001467 /* insert the node into the schema tree */
1468 if (ly_mnode_addchild(parent, retval)) {
1469 goto error;
1470 }
Radek Krejcib7155b52015-06-10 17:03:01 +02001471
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001472 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02001473
1474error:
1475
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001476 ly_mnode_free(retval);
Radek Krejcib4cf2022015-06-03 14:40:05 +02001477
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001478 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02001479}
1480
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001481static struct ly_mnode *
1482read_yin_choice(struct ly_module *module,
1483 struct ly_mnode *parent, struct lyxml_elem *yin, int resolve, struct mnode_list **unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001484{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001485 struct lyxml_elem *sub, *next;
1486 struct ly_ctx *const ctx = module->ctx;
1487 struct ly_mnode *retval, *mnode = NULL;
1488 struct ly_mnode_choice *choice;
1489 const char *value;
1490 char *dflt_str = NULL;
1491 int f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001492
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001493 choice = calloc(1, sizeof *choice);
1494 choice->nodetype = LY_NODE_CHOICE;
1495 choice->prev = (struct ly_mnode *)choice;
1496 retval = (struct ly_mnode *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001497
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001498 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | (resolve ? OPT_INHERIT : 0))) {
1499 goto error;
1500 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001501
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001502 /* process choice's specific children */
1503 LY_TREE_FOR_SAFE(yin->child, next, sub) {
1504 if (!strcmp(sub->name, "container")) {
1505 if (!(mnode = read_yin_container(module, retval, sub, resolve, unres))) {
1506 goto error;
1507 }
1508 } else if (!strcmp(sub->name, "leaf-list")) {
1509 if (!(mnode = read_yin_leaflist(module, retval, sub, resolve))) {
1510 goto error;
1511 }
1512 } else if (!strcmp(sub->name, "leaf")) {
1513 if (!(mnode = read_yin_leaf(module, retval, sub, resolve))) {
1514 goto error;
1515 }
1516 } else if (!strcmp(sub->name, "list")) {
1517 if (!(mnode = read_yin_list(module, retval, sub, resolve, unres))) {
1518 goto error;
1519 }
1520 } else if (!strcmp(sub->name, "case")) {
1521 if (!(mnode = read_yin_case(module, retval, sub, resolve, unres))) {
1522 goto error;
1523 }
1524 } else if (!strcmp(sub->name, "anyxml")) {
1525 if (!(mnode = read_yin_anyxml(module, retval, sub, resolve))) {
1526 goto error;
1527 }
1528 } else if (!strcmp(sub->name, "default")) {
1529 if (dflt_str) {
1530 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
1531 goto error;
1532 }
1533 GETVAL(value, sub, "value");
1534 dflt_str = strdup(value);
1535 } else if (!strcmp(sub->name, "mandatory")) {
1536 if (f_mand) {
1537 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
1538 goto error;
1539 }
1540 /* just checking the flags in leaf is not sufficient, we would allow
1541 * multiple mandatory statements with the "false" value
1542 */
1543 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02001544
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001545 GETVAL(value, sub, "value");
1546 if (!strcmp(value, "true")) {
1547 choice->flags |= LY_NODE_MAND_TRUE;
1548 } else if (strcmp(value, "false")) {
1549 LOGVAL(VE_INARG, LOGLINE(sub), value, sub->name);
1550 goto error;
1551 } /* else false is the default value, so we can ignore it */
Radek Krejcib4cf2022015-06-03 14:40:05 +02001552#if 0
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001553 } else {
1554 LOGVAL(VE_INSTMT, LOGLINE(sub), sub->name);
1555 goto error;
Radek Krejci8eaf9bd2015-06-04 11:05:18 +02001556#else
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001557 } else {
1558 continue;
Radek Krejcib4cf2022015-06-03 14:40:05 +02001559#endif
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001560 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02001561
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001562 if (mnode && check_branch_id(retval, mnode, mnode, LOGLINE(sub))) {
1563 goto error;
1564 }
1565 mnode = NULL;
1566 lyxml_free_elem(ctx, sub);
1567 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02001568
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001569 /* check - default is prohibited in combination with mandatory */
1570 if (dflt_str && (choice->flags & LY_NODE_MAND_TRUE)) {
1571 LOGVAL(VE_SPEC, LOGLINE(yin),
1572 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
1573 goto error;
1574 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02001575
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001576 /* link default with the case */
1577 if (dflt_str) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02001578 choice->dflt = resolve_schema_nodeid(dflt_str, retval, module);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001579 if (!choice->dflt) {
1580 /* default branch not found */
1581 LOGVAL(VE_INARG, LOGLINE(yin), dflt_str, "default");
1582 goto error;
1583 }
1584 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001585
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001586 /* insert the node into the schema tree */
1587 if (parent && ly_mnode_addchild(parent, retval)) {
1588 goto error;
1589 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001590
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001591 free(dflt_str);
Radek Krejcib7155b52015-06-10 17:03:01 +02001592
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001593 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001594
1595error:
1596
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001597 ly_mnode_free(retval);
1598 free(dflt_str);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001599
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001600 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001601}
1602
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001603static struct ly_mnode *
1604read_yin_anyxml(struct ly_module *module, struct ly_mnode *parent, struct lyxml_elem *yin, int resolve)
Radek Krejci863c2852015-06-03 15:47:11 +02001605{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001606 struct ly_mnode *retval;
1607 struct ly_mnode_leaf *anyxml;
1608 struct lyxml_elem *sub, *next;
1609 const char *value;
1610 int r;
1611 int f_mand = 0;
1612 int c_must = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02001613
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001614 anyxml = calloc(1, sizeof *anyxml);
1615 anyxml->nodetype = LY_NODE_ANYXML;
1616 anyxml->prev = (struct ly_mnode *)anyxml;
1617 retval = (struct ly_mnode *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02001618
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001619 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | (resolve ? OPT_INHERIT : 0))) {
1620 goto error;
1621 }
Radek Krejci863c2852015-06-03 15:47:11 +02001622
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001623 LY_TREE_FOR_SAFE(yin->child, next, sub) {
1624 if (!strcmp(sub->name, "mandatory")) {
1625 if (f_mand) {
1626 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
1627 goto error;
1628 }
1629 /* just checking the flags in leaf is not sufficient, we would allow
1630 * multiple mandatory statements with the "false" value
1631 */
1632 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02001633
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001634 GETVAL(value, sub, "value");
1635 if (!strcmp(value, "true")) {
1636 anyxml->flags |= LY_NODE_MAND_TRUE;
1637 } else if (strcmp(value, "false")) {
1638 LOGVAL(VE_INARG, LOGLINE(sub), value, sub->name);
1639 goto error;
1640 }
1641 /* else false is the default value, so we can ignore it */
1642 lyxml_free_elem(module->ctx, sub);
1643 } else if (!strcmp(sub->name, "must")) {
1644 c_must++;
Radek Krejci863c2852015-06-03 15:47:11 +02001645
1646#if 0
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001647 } else {
1648 LOGVAL(VE_INSTMT, LOGLINE(sub), sub->name);
1649 goto error;
Radek Krejci8eaf9bd2015-06-04 11:05:18 +02001650#else
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001651 } else {
1652 continue;
Radek Krejci863c2852015-06-03 15:47:11 +02001653#endif
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001654 }
1655 }
Radek Krejci863c2852015-06-03 15:47:11 +02001656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001657 /* middle part - process nodes with cardinality of 0..n */
1658 if (c_must) {
1659 anyxml->must = calloc(c_must, sizeof *anyxml->must);
1660 }
Radek Krejci863c2852015-06-03 15:47:11 +02001661
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001662 LY_TREE_FOR_SAFE(yin->child, next, sub) {
1663 if (!strcmp(sub->name, "must")) {
1664 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
1665 anyxml->must_size++;
Radek Krejci863c2852015-06-03 15:47:11 +02001666
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001667 if (r) {
1668 goto error;
1669 }
1670 }
Radek Krejci863c2852015-06-03 15:47:11 +02001671
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001672 lyxml_free_elem(module->ctx, sub);
1673 }
Radek Krejci863c2852015-06-03 15:47:11 +02001674
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001675 if (parent && ly_mnode_addchild(parent, retval)) {
1676 goto error;
1677 }
Radek Krejci863c2852015-06-03 15:47:11 +02001678
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001679 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02001680
1681error:
1682
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001683 ly_mnode_free(retval);
Radek Krejci863c2852015-06-03 15:47:11 +02001684
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001685 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02001686}
1687
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001688static struct ly_mnode *
1689read_yin_leaf(struct ly_module *module, struct ly_mnode *parent, struct lyxml_elem *yin, int resolve)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001690{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001691 struct ly_mnode *retval;
1692 struct ly_mnode_leaf *leaf;
1693 struct lyxml_elem *sub, *next;
1694 const char *value;
1695 int r;
1696 int c_must = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001697
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001698 leaf = calloc(1, sizeof *leaf);
1699 leaf->nodetype = LY_NODE_LEAF;
1700 leaf->prev = (struct ly_mnode *)leaf;
1701 retval = (struct ly_mnode *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001702
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001703 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | (resolve ? OPT_INHERIT : 0))) {
1704 goto error;
1705 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001706
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001707 LY_TREE_FOR_SAFE(yin->child, next, sub) {
1708 if (!strcmp(sub->name, "type")) {
1709 if (leaf->type.der) {
1710 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
1711 goto error;
1712 }
1713 if (fill_yin_type(module, parent, sub, &leaf->type)) {
1714 goto error;
1715 }
1716 } else if (!strcmp(sub->name, "default")) {
1717 if (leaf->dflt) {
1718 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
1719 goto error;
1720 }
1721 GETVAL(value, sub, "value");
1722 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
1723 } else if (!strcmp(sub->name, "units")) {
1724 if (leaf->units) {
1725 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
1726 goto error;
1727 }
1728 GETVAL(value, sub, "name");
1729 leaf->units = lydict_insert(module->ctx, value, strlen(value));
1730 } else if (!strcmp(sub->name, "mandatory")) {
1731 if (f_mand) {
1732 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
1733 goto error;
1734 }
1735 /* just checking the flags in leaf is not sufficient, we would allow
1736 * multiple mandatory statements with the "false" value
1737 */
1738 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02001739
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001740 GETVAL(value, sub, "value");
1741 if (!strcmp(value, "true")) {
1742 leaf->flags |= LY_NODE_MAND_TRUE;
1743 } else if (strcmp(value, "false")) {
1744 LOGVAL(VE_INARG, LOGLINE(sub), value, sub->name);
1745 goto error;
1746 } /* else false is the default value, so we can ignore it */
1747 } else if (!strcmp(sub->name, "must")) {
1748 c_must++;
Radek Krejci4c31f122015-06-02 14:51:22 +02001749
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001750 /* skip element free at the end of the loop */
1751 continue;
Radek Krejci1e3f8902015-06-03 11:00:11 +02001752#if 0
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001753 } else {
1754 LOGVAL(VE_INSTMT, LOGLINE(sub), sub->name);
1755 goto error;
Radek Krejci8eaf9bd2015-06-04 11:05:18 +02001756#else
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001757 } else {
1758 continue;
Radek Krejci1e3f8902015-06-03 11:00:11 +02001759#endif
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001760 }
Radek Krejci4c31f122015-06-02 14:51:22 +02001761
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001762 lyxml_free_elem(module->ctx, sub);
1763 }
Radek Krejci4c31f122015-06-02 14:51:22 +02001764
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001765 /* check mandatory parameters */
1766 if (!leaf->type.der) {
1767 LOGVAL(VE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
1768 goto error;
1769 }
1770 if (leaf->dflt && check_default(&leaf->type, leaf->dflt)) {
1771 goto error;
1772 }
Radek Krejci4c31f122015-06-02 14:51:22 +02001773
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001774 /* middle part - process nodes with cardinality of 0..n */
1775 if (c_must) {
1776 leaf->must = calloc(c_must, sizeof *leaf->must);
1777 }
Radek Krejci4c31f122015-06-02 14:51:22 +02001778
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001779 LY_TREE_FOR_SAFE(yin->child, next, sub) {
1780 if (!strcmp(sub->name, "must")) {
1781 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
1782 leaf->must_size++;
Radek Krejci4c31f122015-06-02 14:51:22 +02001783
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001784 if (r) {
1785 goto error;
1786 }
1787 }
Radek Krejci4c31f122015-06-02 14:51:22 +02001788
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001789 lyxml_free_elem(module->ctx, sub);
1790 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001791
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001792 if (parent && ly_mnode_addchild(parent, retval)) {
1793 goto error;
1794 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001795
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001796 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001797
1798error:
1799
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001800 ly_mnode_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001801
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001802 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001803}
1804
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001805static struct ly_mnode *
1806read_yin_leaflist(struct ly_module *module, struct ly_mnode *parent, struct lyxml_elem *yin, int resolve)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001807{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001808 struct ly_mnode *retval;
1809 struct ly_mnode_leaflist *llist;
1810 struct lyxml_elem *sub, *next;
1811 const char *value;
1812 char *endptr;
1813 unsigned long val;
1814 int r;
1815 int c_must = 0;
1816 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001817
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001818 llist = calloc(1, sizeof *llist);
1819 llist->nodetype = LY_NODE_LEAFLIST;
1820 llist->prev = (struct ly_mnode *)llist;
1821 retval = (struct ly_mnode *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001822
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001823 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | (resolve ? OPT_INHERIT : 0))) {
1824 goto error;
1825 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001826
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001827 LY_TREE_FOR_SAFE(yin->child, next, sub) {
1828 if (!strcmp(sub->name, "type")) {
1829 if (llist->type.der) {
1830 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
1831 goto error;
1832 }
1833 if (fill_yin_type(module, parent, sub, &llist->type)) {
1834 goto error;
1835 }
1836 } else if (!strcmp(sub->name, "units")) {
1837 if (llist->units) {
1838 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
1839 goto error;
1840 }
1841 GETVAL(value, sub, "name");
1842 llist->units = lydict_insert(module->ctx, value, strlen(value));
1843 } else if (!strcmp(sub->name, "ordered-by")) {
1844 if (f_ordr) {
1845 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
1846 goto error;
1847 }
1848 /* just checking the flags in llist is not sufficient, we would
1849 * allow multiple ordered-by statements with the "system" value
1850 */
1851 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02001852
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001853 if (llist->flags & LY_NODE_CONFIG_R) {
1854 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
1855 * state data
1856 */
1857 lyxml_free_elem(module->ctx, sub);
1858 continue;
1859 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02001860
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001861 GETVAL(value, sub, "value");
1862 if (!strcmp(value, "user")) {
1863 llist->flags |= LY_NODE_USERORDERED;
1864 } else if (strcmp(value, "system")) {
1865 LOGVAL(VE_INARG, LOGLINE(sub), value, sub->name);
1866 goto error;
1867 } /* else system is the default value, so we can ignore it */
1868 } else if (!strcmp(sub->name, "must")) {
1869 c_must++;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02001870
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001871 /* skip element free at the end of the loop */
1872 continue;
1873 } else if (!strcmp(sub->name, "min-elements")) {
1874 if (f_min) {
1875 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
1876 goto error;
1877 }
1878 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02001879
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001880 GETVAL(value, sub, "value");
1881 while (isspace(value[0])) {
1882 value++;
1883 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02001884
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001885 /* convert it to uint32_t */
1886 errno = 0;
1887 endptr = NULL;
1888 val = strtoul(value, &endptr, 10);
1889 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
1890 LOGVAL(VE_INARG, LOGLINE(sub), value, sub->name);
1891 goto error;
1892 }
1893 llist->min = (uint32_t) val;
1894 } else if (!strcmp(sub->name, "max-elements")) {
1895 if (f_max) {
1896 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
1897 goto error;
1898 }
1899 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02001900
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001901 GETVAL(value, sub, "value");
1902 while (isspace(value[0])) {
1903 value++;
1904 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02001905
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001906 /* convert it to uint32_t */
1907 errno = 0;
1908 endptr = NULL;
1909 val = strtoul(value, &endptr, 10);
1910 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
1911 LOGVAL(VE_INARG, LOGLINE(sub), value, sub->name);
1912 goto error;
1913 }
1914 llist->max = (uint32_t) val;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02001915
Radek Krejci1e3f8902015-06-03 11:00:11 +02001916#if 0
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001917 } else {
1918 LOGVAL(VE_INSTMT, LOGLINE(sub), sub->name);
1919 goto error;
Radek Krejci8eaf9bd2015-06-04 11:05:18 +02001920#else
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001921 } else {
1922 continue;
Radek Krejci1e3f8902015-06-03 11:00:11 +02001923#endif
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001924 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02001925
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001926 lyxml_free_elem(module->ctx, sub);
1927 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02001928
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001929 /* check constraints */
1930 if (!llist->type.der) {
1931 LOGVAL(VE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
1932 goto error;
1933 }
1934 if (llist->max && llist->min > llist->max) {
1935 LOGVAL(VE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
1936 goto error;
1937 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02001938
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001939 /* middle part - process nodes with cardinality of 0..n */
1940 if (c_must) {
1941 llist->must = calloc(c_must, sizeof *llist->must);
1942 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02001943
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001944 LY_TREE_FOR_SAFE(yin->child, next, sub) {
1945 if (!strcmp(sub->name, "must")) {
1946 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
1947 llist->must_size++;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02001948
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001949 if (r) {
1950 goto error;
1951 }
1952 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02001953
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001954 lyxml_free_elem(module->ctx, sub);
1955 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001956
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001957 if (parent && ly_mnode_addchild(parent, retval)) {
1958 goto error;
1959 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001960
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001961 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001962
1963error:
1964
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001965 ly_mnode_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02001966
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001967 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001968}
1969
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001970static struct ly_mnode *
1971read_yin_list(struct ly_module *module,
1972 struct ly_mnode *parent, struct lyxml_elem *yin, int resolve, struct mnode_list **unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001973{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001974 struct ly_mnode *retval, *mnode;
1975 struct ly_mnode_list *list;
1976 struct ly_unique *uniq_s;
1977 struct lyxml_elem *sub, *next, root, uniq;
1978 int i, r;
1979 size_t len;
1980 int c_tpdf = 0, c_must = 0, c_uniq = 0;
1981 int f_ordr = 0, f_max = 0, f_min = 0;
1982 const char *key_str = NULL, *uniq_str, *value;
1983 char *auxs;
1984 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001985
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001986 /* init */
1987 memset(&root, 0, sizeof root);
1988 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02001989
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001990 list = calloc(1, sizeof *list);
1991 list->nodetype = LY_NODE_LIST;
1992 list->prev = (struct ly_mnode *)list;
1993 retval = (struct ly_mnode *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001994
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001995 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | (resolve ? OPT_INHERIT : 0))) {
1996 goto error;
1997 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001998
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001999 /* process list's specific children */
2000 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2001 /* data statements */
2002 if (!strcmp(sub->name, "container") ||
2003 !strcmp(sub->name, "leaf-list") ||
2004 !strcmp(sub->name, "leaf") ||
2005 !strcmp(sub->name, "list") ||
2006 !strcmp(sub->name, "choice") ||
2007 !strcmp(sub->name, "uses") ||
2008 !strcmp(sub->name, "grouping") ||
2009 !strcmp(sub->name, "anyxml")) {
2010 lyxml_unlink_elem(sub);
2011 lyxml_add_child(&root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002012
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002013 /* array counters */
2014 } else if (!strcmp(sub->name, "key")) {
2015 /* check cardinality 0..1 */
2016 if (list->keys_size) {
2017 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, list->name);
2018 goto error;
2019 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02002020
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002021 /* count the number of keys */
2022 GETVAL(value, sub, "value");
2023 key_str = value;
2024 while ((value = strpbrk(value, " \t\n"))) {
2025 list->keys_size++;
2026 while (isspace(*value)) {
2027 value++;
2028 }
2029 }
2030 list->keys_size++;
2031 list->keys = calloc(list->keys_size, sizeof *list->keys);
2032 } else if (!strcmp(sub->name, "unique")) {
2033 c_uniq++;
2034 lyxml_unlink_elem(sub);
2035 lyxml_add_child(&uniq, sub);
2036 } else if (!strcmp(sub->name, "typedef")) {
2037 c_tpdf++;
2038 } else if (!strcmp(sub->name, "must")) {
2039 c_must++;
Radek Krejci345ad742015-06-03 11:04:18 +02002040
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002041 /* optional stetments */
2042 } else if (!strcmp(sub->name, "ordered-by")) {
2043 if (f_ordr) {
2044 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
2045 goto error;
2046 }
2047 /* just checking the flags in llist is not sufficient, we would
2048 * allow multiple ordered-by statements with the "system" value
2049 */
2050 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02002051
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002052 if (list->flags & LY_NODE_CONFIG_R) {
2053 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
2054 * state data
2055 */
2056 lyxml_free_elem(module->ctx, sub);
2057 continue;
2058 }
Radek Krejci345ad742015-06-03 11:04:18 +02002059
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002060 GETVAL(value, sub, "value");
2061 if (!strcmp(value, "user")) {
2062 list->flags |= LY_NODE_USERORDERED;
2063 } else if (strcmp(value, "system")) {
2064 LOGVAL(VE_INARG, LOGLINE(sub), value, sub->name);
2065 goto error;
2066 }
2067 /* else system is the default value, so we can ignore it */
2068 lyxml_free_elem(module->ctx, sub);
2069 } else if (!strcmp(sub->name, "min-elements")) {
2070 if (f_min) {
2071 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
2072 goto error;
2073 }
2074 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02002075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002076 GETVAL(value, sub, "value");
2077 while (isspace(value[0])) {
2078 value++;
2079 }
Radek Krejci345ad742015-06-03 11:04:18 +02002080
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002081 /* convert it to uint32_t */
2082 errno = 0;
2083 auxs = NULL;
2084 val = strtoul(value, &auxs, 10);
2085 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
2086 LOGVAL(VE_INARG, LOGLINE(sub), value, sub->name);
2087 goto error;
2088 }
2089 list->min = (uint32_t) val;
2090 lyxml_free_elem(module->ctx, sub);
2091 } else if (!strcmp(sub->name, "max-elements")) {
2092 if (f_max) {
2093 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
2094 goto error;
2095 }
2096 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02002097
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002098 GETVAL(value, sub, "value");
2099 while (isspace(value[0])) {
2100 value++;
2101 }
Radek Krejci345ad742015-06-03 11:04:18 +02002102
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002103 /* convert it to uint32_t */
2104 errno = 0;
2105 auxs = NULL;
2106 val = strtoul(value, &auxs, 10);
2107 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
2108 LOGVAL(VE_INARG, LOGLINE(sub), value, sub->name);
2109 goto error;
2110 }
2111 list->max = (uint32_t) val;
2112 lyxml_free_elem(module->ctx, sub);
2113 }
2114 }
Radek Krejci345ad742015-06-03 11:04:18 +02002115
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002116 /* check - if list is configuration, key statement is mandatory */
2117 if ((list->flags & LY_NODE_CONFIG_W) && !key_str) {
2118 LOGVAL(VE_MISSSTMT2, LOGLINE(yin), "key", "list");
2119 goto error;
2120 }
2121 if (list->max && list->min > list->max) {
2122 LOGVAL(VE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
2123 goto error;
2124 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002125
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002126 /* middle part - process nodes with cardinality of 0..n except the data nodes */
2127 if (c_tpdf) {
2128 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
2129 }
2130 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2131 if (!strcmp(sub->name, "typedef")) {
2132 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size]);
2133 list->tpdf_size++;
Radek Krejcid7f0d012015-05-25 15:04:52 +02002134
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002135 if (r) {
2136 goto error;
2137 }
2138 lyxml_free_elem(module->ctx, sub);
2139 }
2140 }
Radek Krejci25d782a2015-05-22 15:03:23 +02002141
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002142 /* last part - process data nodes */
2143 LY_TREE_FOR_SAFE(root.child, next, sub) {
2144 if (!strcmp(sub->name, "container")) {
2145 mnode = read_yin_container(module, retval, sub, resolve, unres);
2146 } else if (!strcmp(sub->name, "leaf-list")) {
2147 mnode = read_yin_leaflist(module, retval, sub, resolve);
2148 } else if (!strcmp(sub->name, "leaf")) {
2149 mnode = read_yin_leaf(module, retval, sub, resolve);
2150 } else if (!strcmp(sub->name, "list")) {
2151 mnode = read_yin_list(module, retval, sub, resolve, unres);
2152 } else if (!strcmp(sub->name, "choice")) {
2153 mnode = read_yin_choice(module, retval, sub, resolve, unres);
2154 } else if (!strcmp(sub->name, "uses")) {
2155 mnode = read_yin_uses(module, retval, sub, resolve, unres);
2156 } else if (!strcmp(sub->name, "grouping")) {
2157 mnode = read_yin_grouping(module, retval, sub, resolve, unres);
2158 } else if (!strcmp(sub->name, "anyxml")) {
2159 mnode = read_yin_anyxml(module, retval, sub, resolve);
2160 } else {
2161 /* TODO error */
2162 continue;
2163 }
2164 lyxml_free_elem(module->ctx, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002165
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002166 if (!mnode) {
2167 goto error;
2168 }
2169 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002170
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002171 if (parent && ly_mnode_addchild(parent, retval)) {
2172 goto error;
2173 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002174
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002175 if (!key_str) {
2176 /* config false list without a key */
2177 return retval;
2178 }
Radek Krejci812b10a2015-05-28 16:48:25 +02002179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002180 /* link key leafs into the list structure and check all constraints */
2181 for (i = 0; i < list->keys_size; i++) {
2182 /* get the key name */
2183 if ((value = strpbrk(key_str, " \t\n"))) {
2184 len = value - key_str;
2185 while (isspace(*value)) {
2186 value++;
2187 }
2188 } else {
2189 len = strlen(key_str);
2190 }
Radek Krejci3a734ed2015-05-26 15:23:18 +02002191
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002192 list->keys[i] = find_leaf(retval, key_str, len);
Radek Krejci8bc9ca02015-06-04 15:52:46 +02002193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002194 if (check_key(list->keys[i], list->flags, list->keys, i, LOGLINE(yin), key_str, len)) {
2195 goto error;
2196 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02002197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002198 /* prepare for next iteration */
2199 while (value && isspace(*value)) {
2200 value++;
2201 }
2202 key_str = value;
2203 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02002204
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002205 /* process unique statements */
2206 if (c_uniq) {
2207 list->unique = calloc(c_uniq, sizeof *list->unique);
2208 }
2209 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
2210 /* count the number of unique values */
2211 GETVAL(value, sub, "tag");
2212 uniq_str = value;
2213 uniq_s = &list->unique[list->unique_size];
2214 while ((value = strpbrk(value, " \t\n"))) {
2215 uniq_s->leafs_size++;
2216 while (isspace(*value)) {
2217 value++;
2218 }
2219 }
2220 uniq_s->leafs_size++;
2221 uniq_s->leafs = calloc(uniq_s->leafs_size, sizeof *uniq_s->leafs);
2222 list->unique_size++;
Radek Krejcid7f0d012015-05-25 15:04:52 +02002223
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002224 /* interconnect unique values with the leafs */
2225 for (i = 0; i < uniq_s->leafs_size; i++) {
2226 if ((value = strpbrk(uniq_str, " \t\n"))) {
2227 len = value - uniq_str;
2228 while (isspace(*value)) {
2229 value++;
2230 }
2231 } else {
2232 len = strlen(uniq_str);
2233 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02002234
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002235 uniq_s->leafs[i] = find_leaf(retval, uniq_str, len);
2236 if (check_key(uniq_s->leafs[i], list->flags, uniq_s->leafs, i, LOGLINE(yin), uniq_str, len)) {
2237 goto error;
2238 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02002239
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002240 /* prepare for next iteration */
2241 while (value && isspace(*value)) {
2242 value++;
2243 }
2244 uniq_str = value;
2245 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02002246
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002247 lyxml_free_elem(module->ctx, sub);
2248 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02002249
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002250 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002251
2252error:
2253
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002254 ly_mnode_free(retval);
2255 while (root.child) {
2256 lyxml_free_elem(module->ctx, root.child);
2257 }
2258 while (uniq.child) {
2259 lyxml_free_elem(module->ctx, uniq.child);
2260 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002261
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002262 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002263}
2264
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002265static struct ly_mnode *
2266read_yin_container(struct ly_module *module,
2267 struct ly_mnode *parent, struct lyxml_elem *yin, int resolve, struct mnode_list **unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002268{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002269 struct lyxml_elem *sub, *next, root;
2270 struct ly_mnode *mnode = NULL;
2271 struct ly_mnode *retval;
2272 struct ly_mnode_container *cont;
2273 const char *value;
2274 int r;
2275 int c_tpdf = 0, c_must = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002276
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002277 /* init */
2278 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02002279
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002280 cont = calloc(1, sizeof *cont);
2281 cont->nodetype = LY_NODE_CONTAINER;
2282 cont->prev = (struct ly_mnode *)cont;
2283 retval = (struct ly_mnode *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002285 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | (resolve ? OPT_INHERIT : 0))) {
2286 goto error;
2287 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002288
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002289 /* process container's specific children */
2290 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2291 if (!strcmp(sub->name, "presence")) {
2292 if (cont->presence) {
2293 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
2294 goto error;
2295 }
2296 GETVAL(value, sub, "value");
2297 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02002298
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002299 lyxml_free_elem(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02002300
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002301 /* data statements */
2302 } else if (!strcmp(sub->name, "container") ||
2303 !strcmp(sub->name, "leaf-list") ||
2304 !strcmp(sub->name, "leaf") ||
2305 !strcmp(sub->name, "list") ||
2306 !strcmp(sub->name, "choice") ||
2307 !strcmp(sub->name, "uses") ||
2308 !strcmp(sub->name, "grouping") ||
2309 !strcmp(sub->name, "anyxml")) {
2310 lyxml_unlink_elem(sub);
2311 lyxml_add_child(&root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002312
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002313 /* array counters */
2314 } else if (!strcmp(sub->name, "typedef")) {
2315 c_tpdf++;
2316 } else if (!strcmp(sub->name, "must")) {
2317 c_must++;
Radek Krejci1e3f8902015-06-03 11:00:11 +02002318#if 0
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002319 } else {
2320 LOGVAL(VE_INSTMT, LOGLINE(sub), sub->name);
2321 goto error;
Radek Krejci8eaf9bd2015-06-04 11:05:18 +02002322#else
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002323 } else {
2324 continue;
Radek Krejci1e3f8902015-06-03 11:00:11 +02002325#endif
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002326 }
2327 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002328
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002329 /* middle part - process nodes with cardinality of 0..n except the data nodes */
2330 if (c_tpdf) {
2331 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
2332 }
2333 if (c_must) {
2334 cont->must = calloc(c_must, sizeof *cont->must);
2335 }
Radek Krejci800af702015-06-02 13:46:01 +02002336
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002337 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2338 if (!strcmp(sub->name, "typedef")) {
2339 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size]);
2340 cont->tpdf_size++;
Radek Krejci25d782a2015-05-22 15:03:23 +02002341
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002342 if (r) {
2343 goto error;
2344 }
2345 } else if (!strcmp(sub->name, "must")) {
2346 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
2347 cont->must_size++;
Radek Krejci800af702015-06-02 13:46:01 +02002348
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002349 if (r) {
2350 goto error;
2351 }
2352 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002353
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002354 lyxml_free_elem(module->ctx, sub);
2355 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002357 /* last part - process data nodes */
2358 LY_TREE_FOR_SAFE(root.child, next, sub) {
2359 if (!strcmp(sub->name, "container")) {
2360 mnode = read_yin_container(module, retval, sub, resolve, unres);
2361 } else if (!strcmp(sub->name, "leaf-list")) {
2362 mnode = read_yin_leaflist(module, retval, sub, resolve);
2363 } else if (!strcmp(sub->name, "leaf")) {
2364 mnode = read_yin_leaf(module, retval, sub, resolve);
2365 } else if (!strcmp(sub->name, "list")) {
2366 mnode = read_yin_list(module, retval, sub, resolve, unres);
2367 } else if (!strcmp(sub->name, "choice")) {
2368 mnode = read_yin_choice(module, retval, sub, resolve, unres);
2369 } else if (!strcmp(sub->name, "uses")) {
2370 mnode = read_yin_uses(module, retval, sub, resolve, unres);
2371 } else if (!strcmp(sub->name, "grouping")) {
2372 mnode = read_yin_grouping(module, retval, sub, resolve, unres);
2373 } else if (!strcmp(sub->name, "anyxml")) {
2374 mnode = read_yin_anyxml(module, retval, sub, resolve);
2375 }
2376 lyxml_free_elem(module->ctx, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002377
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002378 if (!mnode) {
2379 goto error;
2380 }
2381 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002382
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002383 if (parent && ly_mnode_addchild(parent, retval)) {
2384 goto error;
2385 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002386
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002387 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002388
2389error:
2390
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002391 ly_mnode_free(retval);
2392 while (root.child) {
2393 lyxml_free_elem(module->ctx, root.child);
2394 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002395
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002396 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002397}
2398
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002399static struct ly_mnode *
2400read_yin_grouping(struct ly_module *module,
2401 struct ly_mnode *parent, struct lyxml_elem *node, int resolve, struct mnode_list **unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002402{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002403 struct lyxml_elem *sub, *next, root;
2404 struct ly_mnode *mnode = NULL;
2405 struct ly_mnode *retval;
2406 struct ly_mnode_grp *grp;
2407 int r;
2408 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002409
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002410 /* init */
2411 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02002412
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002413 grp = calloc(1, sizeof *grp);
2414 grp->nodetype = LY_NODE_GROUPING;
2415 grp->prev = (struct ly_mnode *)grp;
2416 retval = (struct ly_mnode *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002417
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002418 if (read_yin_common(module, parent, retval, node, OPT_IDENT | OPT_MODULE)) {
2419 goto error;
2420 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002421
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002422 LY_TREE_FOR_SAFE(node->child, next, sub) {
2423 /* data statements */
2424 if (!strcmp(sub->name, "container") ||
2425 !strcmp(sub->name, "leaf-list") ||
2426 !strcmp(sub->name, "leaf") ||
2427 !strcmp(sub->name, "list") ||
2428 !strcmp(sub->name, "choice") ||
2429 !strcmp(sub->name, "uses") ||
2430 !strcmp(sub->name, "grouping") ||
2431 !strcmp(sub->name, "anyxml")) {
2432 lyxml_unlink_elem(sub);
2433 lyxml_add_child(&root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002434
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002435 /* array counters */
2436 } else if (!strcmp(sub->name, "typedef")) {
2437 c_tpdf++;
2438 } else {
2439 LOGVAL(VE_INSTMT, LOGLINE(sub), sub->name);
2440 goto error;
2441 }
2442 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002443
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002444 /* middle part - process nodes with cardinality of 0..n except the data nodes */
2445 if (c_tpdf) {
2446 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
2447 }
2448 LY_TREE_FOR_SAFE(node->child, next, sub) {
2449 if (!strcmp(sub->name, "typedef")) {
2450 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size]);
2451 grp->tpdf_size++;
Radek Krejci25d782a2015-05-22 15:03:23 +02002452
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002453 if (r) {
2454 goto error;
2455 }
2456 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002457
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002458 lyxml_free_elem(module->ctx, sub);
2459 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002460
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002461 /* last part - process data nodes */
2462 LY_TREE_FOR_SAFE(root.child, next, sub) {
2463 if (!strcmp(sub->name, "container")) {
2464 mnode = read_yin_container(module, retval, sub, resolve, unres);
2465 } else if (!strcmp(sub->name, "leaf-list")) {
2466 mnode = read_yin_leaflist(module, retval, sub, resolve);
2467 } else if (!strcmp(sub->name, "leaf")) {
2468 mnode = read_yin_leaf(module, retval, sub, resolve);
2469 } else if (!strcmp(sub->name, "list")) {
2470 mnode = read_yin_list(module, retval, sub, resolve, unres);
2471 } else if (!strcmp(sub->name, "choice")) {
2472 mnode = read_yin_choice(module, retval, sub, resolve, unres);
2473 } else if (!strcmp(sub->name, "uses")) {
2474 mnode = read_yin_uses(module, retval, sub, resolve, unres);
2475 } else if (!strcmp(sub->name, "grouping")) {
2476 mnode = read_yin_grouping(module, retval, sub, resolve, unres);
2477 } else if (!strcmp(sub->name, "anyxml")) {
2478 mnode = read_yin_anyxml(module, retval, sub, resolve);
2479 }
2480 lyxml_free_elem(module->ctx, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002481
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002482 if (!mnode) {
2483 goto error;
2484 }
2485 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002486
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002487 if (parent && ly_mnode_addchild(parent, retval)) {
2488 goto error;
2489 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002490
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002491 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002492
2493error:
2494
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002495 ly_mnode_free(retval);
2496 while (root.child) {
2497 lyxml_free_elem(module->ctx, root.child);
2498 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002499
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002500 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002501}
2502
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002503static struct ly_mnode *
2504read_yin_input_output(struct ly_module *module,
2505 struct ly_mnode *parent, struct lyxml_elem *yin, int resolve, struct mnode_list **unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02002506{
Radek Krejcie0674f82015-06-15 13:58:51 +02002507 struct lyxml_elem *sub, *next, root;
Michal Vasko38d01f72015-06-15 09:41:06 +02002508 struct ly_mnode *mnode = NULL;
2509 struct ly_mnode *retval;
2510 struct ly_mnode_input_output *inout;
2511 int r;
2512 int c_tpdf = 0;
2513
Radek Krejcie0674f82015-06-15 13:58:51 +02002514 /* init */
2515 memset(&root, 0, sizeof root);
2516
Michal Vasko38d01f72015-06-15 09:41:06 +02002517 inout = calloc(1, sizeof *inout);
2518
2519 if (!strcmp(yin->name, "input")) {
2520 inout->nodetype = LY_NODE_INPUT;
2521 } else if (!strcmp(yin->name, "output")) {
2522 inout->nodetype = LY_NODE_OUTPUT;
2523 } else {
2524 assert(0);
2525 }
2526
2527 inout->prev = (struct ly_mnode *)inout;
2528 retval = (struct ly_mnode *)inout;
2529
Michal Vaskoebeac942015-06-15 12:11:50 +02002530 if (read_yin_common(module, parent, retval, yin, OPT_MODULE)) {
2531 goto error;
2532 }
2533
Michal Vasko38d01f72015-06-15 09:41:06 +02002534 /* data statements */
2535 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2536 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002537 !strcmp(sub->name, "leaf-list") ||
2538 !strcmp(sub->name, "leaf") ||
2539 !strcmp(sub->name, "list") ||
2540 !strcmp(sub->name, "choice") ||
2541 !strcmp(sub->name, "uses") ||
2542 !strcmp(sub->name, "grouping") ||
2543 !strcmp(sub->name, "anyxml")) {
Michal Vasko38d01f72015-06-15 09:41:06 +02002544 lyxml_unlink_elem(sub);
2545 lyxml_add_child(&root, sub);
2546
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002547 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02002548 } else if (!strcmp(sub->name, "typedef")) {
2549 c_tpdf++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002550#if 0
Michal Vasko38d01f72015-06-15 09:41:06 +02002551 } else {
2552 LOGVAL(VE_INSTMT, LOGLINE(sub), sub->name);
2553 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002554#else
Michal Vasko38d01f72015-06-15 09:41:06 +02002555 } else {
2556 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002557#endif
Michal Vasko38d01f72015-06-15 09:41:06 +02002558 }
2559 }
2560
2561 /* middle part - process nodes with cardinality of 0..n except the data nodes */
2562 if (c_tpdf) {
2563 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
2564 }
2565
2566 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2567 if (!strcmp(sub->name, "typedef")) {
2568 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size]);
2569 inout->tpdf_size++;
2570
2571 if (r) {
2572 goto error;
2573 }
2574 }
2575
2576 lyxml_free_elem(module->ctx, sub);
2577 }
2578
2579 /* last part - process data nodes */
2580 LY_TREE_FOR_SAFE(root.child, next, sub) {
2581 if (!strcmp(sub->name, "container")) {
2582 mnode = read_yin_container(module, retval, sub, resolve, unres);
2583 } else if (!strcmp(sub->name, "leaf-list")) {
2584 mnode = read_yin_leaflist(module, retval, sub, resolve);
2585 } else if (!strcmp(sub->name, "leaf")) {
2586 mnode = read_yin_leaf(module, retval, sub, resolve);
2587 } else if (!strcmp(sub->name, "list")) {
2588 mnode = read_yin_list(module, retval, sub, resolve, unres);
2589 } else if (!strcmp(sub->name, "choice")) {
2590 mnode = read_yin_choice(module, retval, sub, resolve, unres);
2591 } else if (!strcmp(sub->name, "uses")) {
2592 mnode = read_yin_uses(module, retval, sub, resolve, unres);
2593 } else if (!strcmp(sub->name, "grouping")) {
2594 mnode = read_yin_grouping(module, retval, sub, resolve, unres);
2595 } else if (!strcmp(sub->name, "anyxml")) {
2596 mnode = read_yin_anyxml(module, retval, sub, resolve);
2597 }
2598 lyxml_free_elem(module->ctx, sub);
2599
2600 if (!mnode) {
2601 goto error;
2602 }
2603 }
2604
2605 if (parent && ly_mnode_addchild(parent, retval)) {
2606 goto error;
2607 }
2608
2609 return retval;
2610
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002611error:
Michal Vasko38d01f72015-06-15 09:41:06 +02002612
2613 ly_mnode_free(retval);
Radek Krejci594042f2015-06-15 15:05:47 +02002614 LY_TREE_FOR_SAFE(root.child, next, sub) {
2615 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02002616 }
2617
2618 return NULL;
2619}
2620
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002621static struct ly_mnode *
2622read_yin_notif(struct ly_module *module,
2623 struct ly_mnode *parent, struct lyxml_elem *yin, int resolve, struct mnode_list **unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02002624{
Michal Vaskoc6551b32015-06-16 10:51:43 +02002625 struct lyxml_elem *sub, *next, root;
Michal Vasko0ea41032015-06-16 08:53:55 +02002626 struct ly_mnode *mnode = NULL;
2627 struct ly_mnode *retval;
2628 struct ly_mnode_notif *notif;
2629 int r;
2630 int c_tpdf = 0;
2631
Michal Vaskoc6551b32015-06-16 10:51:43 +02002632 memset(&root, 0, sizeof root);
2633
Michal Vasko0ea41032015-06-16 08:53:55 +02002634 notif = calloc(1, sizeof *notif);
2635 notif->nodetype = LY_NODE_NOTIF;
2636 notif->prev = (struct ly_mnode *)notif;
2637 retval = (struct ly_mnode *)notif;
2638
2639 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
2640 goto error;
2641 }
2642
2643 /* process rpc's specific children */
2644 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2645 /* data statements */
2646 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002647 !strcmp(sub->name, "leaf-list") ||
2648 !strcmp(sub->name, "leaf") ||
2649 !strcmp(sub->name, "list") ||
2650 !strcmp(sub->name, "choice") ||
2651 !strcmp(sub->name, "uses") ||
2652 !strcmp(sub->name, "grouping") ||
2653 !strcmp(sub->name, "anyxml")) {
Michal Vasko0ea41032015-06-16 08:53:55 +02002654 lyxml_unlink_elem(sub);
2655 lyxml_add_child(&root, sub);
2656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002657 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02002658 } else if (!strcmp(sub->name, "typedef")) {
2659 c_tpdf++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002660#if 0
Michal Vasko0ea41032015-06-16 08:53:55 +02002661 } else {
2662 LOGVAL(VE_INSTMT, LOGLINE(sub), sub->name);
2663 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002664#else
Michal Vasko0ea41032015-06-16 08:53:55 +02002665 } else {
2666 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002667#endif
Michal Vasko0ea41032015-06-16 08:53:55 +02002668 }
2669 }
2670
2671 /* middle part - process nodes with cardinality of 0..n except the data nodes */
2672 if (c_tpdf) {
2673 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
2674 }
2675
2676 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2677 if (!strcmp(sub->name, "typedef")) {
2678 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size]);
2679 notif->tpdf_size++;
2680
2681 if (r) {
2682 goto error;
2683 }
2684 }
2685
2686 lyxml_free_elem(module->ctx, sub);
2687 }
2688
2689 /* last part - process data nodes */
2690 LY_TREE_FOR_SAFE(root.child, next, sub) {
2691 if (!strcmp(sub->name, "container")) {
2692 mnode = read_yin_container(module, retval, sub, resolve, unres);
2693 } else if (!strcmp(sub->name, "leaf-list")) {
2694 mnode = read_yin_leaflist(module, retval, sub, resolve);
2695 } else if (!strcmp(sub->name, "leaf")) {
2696 mnode = read_yin_leaf(module, retval, sub, resolve);
2697 } else if (!strcmp(sub->name, "list")) {
2698 mnode = read_yin_list(module, retval, sub, resolve, unres);
2699 } else if (!strcmp(sub->name, "choice")) {
2700 mnode = read_yin_choice(module, retval, sub, resolve, unres);
2701 } else if (!strcmp(sub->name, "uses")) {
2702 mnode = read_yin_uses(module, retval, sub, resolve, unres);
2703 } else if (!strcmp(sub->name, "grouping")) {
2704 mnode = read_yin_grouping(module, retval, sub, resolve, unres);
2705 } else if (!strcmp(sub->name, "anyxml")) {
2706 mnode = read_yin_anyxml(module, retval, sub, resolve);
2707 }
2708 lyxml_free_elem(module->ctx, sub);
2709
2710 if (!mnode) {
2711 goto error;
2712 }
2713 }
2714
2715 if (parent && ly_mnode_addchild(parent, retval)) {
2716 goto error;
2717 }
2718
2719 return retval;
2720
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002721error:
Michal Vasko0ea41032015-06-16 08:53:55 +02002722
2723 ly_mnode_free(retval);
2724 while (root.child) {
2725 lyxml_free_elem(module->ctx, root.child);
2726 }
2727
2728 return NULL;
2729}
2730
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002731static struct ly_mnode *
2732read_yin_rpc(struct ly_module *module,
2733 struct ly_mnode *parent, struct lyxml_elem *yin, int resolve, struct mnode_list **unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02002734{
Radek Krejcie0674f82015-06-15 13:58:51 +02002735 struct lyxml_elem *sub, *next, root;
Michal Vasko38d01f72015-06-15 09:41:06 +02002736 struct ly_mnode *mnode = NULL;
2737 struct ly_mnode *retval;
2738 struct ly_mnode_rpc *rpc;
2739 int r;
2740 int c_tpdf = 0;
2741
Radek Krejcie0674f82015-06-15 13:58:51 +02002742 /* init */
2743 memset(&root, 0, sizeof root);
2744
Michal Vasko38d01f72015-06-15 09:41:06 +02002745 rpc = calloc(1, sizeof *rpc);
2746 rpc->nodetype = LY_NODE_RPC;
2747 rpc->prev = (struct ly_mnode *)rpc;
2748 retval = (struct ly_mnode *)rpc;
2749
2750 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
2751 goto error;
2752 }
2753
2754 /* process rpc's specific children */
2755 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2756 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002757 if (rpc->child
2758 && (rpc->child->nodetype == LY_NODE_INPUT
2759 || (rpc->child->next && rpc->child->next->nodetype == LY_NODE_INPUT))) {
Michal Vasko38d01f72015-06-15 09:41:06 +02002760 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
2761 goto error;
2762 }
2763 lyxml_unlink_elem(sub);
2764 lyxml_add_child(&root, sub);
2765 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002766 if (rpc->child
2767 && (rpc->child->nodetype == LY_NODE_INPUT
2768 || (rpc->child->next && rpc->child->next->nodetype == LY_NODE_INPUT))) {
Michal Vasko38d01f72015-06-15 09:41:06 +02002769 LOGVAL(VE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
2770 goto error;
2771 }
2772 lyxml_unlink_elem(sub);
2773 lyxml_add_child(&root, sub);
2774
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002775 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02002776 } else if (!strcmp(sub->name, "grouping")) {
2777 lyxml_unlink_elem(sub);
2778 lyxml_add_child(&root, sub);
2779
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002780 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02002781 } else if (!strcmp(sub->name, "typedef")) {
2782 c_tpdf++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002783#if 0
Michal Vasko38d01f72015-06-15 09:41:06 +02002784 } else {
2785 LOGVAL(VE_INSTMT, LOGLINE(sub), sub->name);
2786 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002787#else
Michal Vasko38d01f72015-06-15 09:41:06 +02002788 } else {
2789 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002790#endif
Michal Vasko38d01f72015-06-15 09:41:06 +02002791 }
2792 }
2793
2794 /* middle part - process nodes with cardinality of 0..n except the data nodes */
2795 if (c_tpdf) {
2796 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
2797 }
2798
2799 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2800 if (!strcmp(sub->name, "typedef")) {
2801 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size]);
2802 rpc->tpdf_size++;
2803
2804 if (r) {
2805 goto error;
2806 }
2807 }
2808
2809 lyxml_free_elem(module->ctx, sub);
2810 }
2811
2812 /* last part - process data nodes */
2813 LY_TREE_FOR_SAFE(root.child, next, sub) {
2814 if (!strcmp(sub->name, "grouping")) {
2815 mnode = read_yin_grouping(module, retval, sub, resolve, unres);
2816 } else if (!strcmp(sub->name, "input")) {
2817 mnode = read_yin_input_output(module, retval, sub, resolve, unres);
2818 } else if (!strcmp(sub->name, "output")) {
2819 mnode = read_yin_input_output(module, retval, sub, resolve, unres);
2820 }
2821 lyxml_free_elem(module->ctx, sub);
2822
2823 if (!mnode) {
2824 goto error;
2825 }
2826 }
2827
2828 if (parent && ly_mnode_addchild(parent, retval)) {
2829 goto error;
2830 }
2831
2832 return retval;
2833
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002834error:
Michal Vasko38d01f72015-06-15 09:41:06 +02002835
2836 ly_mnode_free(retval);
Radek Krejci594042f2015-06-15 15:05:47 +02002837 LY_TREE_FOR_SAFE(root.child, next, sub) {
2838 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02002839 }
2840
2841 return NULL;
2842}
2843
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002844static int
2845find_grouping(struct ly_mnode *parent, struct ly_mnode_uses *uses, int line)
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02002846{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002847 struct ly_module *searchmod = NULL, *module = uses->module;
2848 struct ly_mnode *mnode, *mnode_aux;
2849 const char *name;
2850 int prefix_len = 0;
2851 int i;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02002852
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002853 /* get referenced grouping */
2854 name = strchr(uses->name, ':');
2855 if (!name) {
2856 /* no prefix, search in local tree */
2857 name = uses->name;
2858 } else {
2859 /* there is some prefix, check if it refer the same data model */
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02002860
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002861 /* set name to correct position after colon */
2862 prefix_len = name - uses->name;
2863 name++;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02002864
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002865 if (!strncmp(uses->name, module->prefix, prefix_len) && !module->prefix[prefix_len]) {
2866 /* prefix refers to the current module, ignore it */
2867 prefix_len = 0;
2868 }
2869 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02002870
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002871 /* search */
2872 if (prefix_len) {
2873 /* in top-level groupings of some other module */
2874 for (i = 0; i < module->imp_size; i++) {
2875 if (!strncmp(module->imp[i].prefix, uses->name, prefix_len)
2876 && !module->imp[i].prefix[prefix_len]) {
2877 searchmod = module->imp[i].module;
2878 break;
2879 }
2880 }
2881 if (!searchmod) {
2882 /* uses refers unknown data model */
2883 LOGVAL(VE_INPREFIX, line, name);
2884 return EXIT_FAILURE;
2885 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02002886
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002887 LY_TREE_FOR(searchmod->data, mnode) {
2888 if (mnode->nodetype == LY_NODE_GROUPING && !strcmp(mnode->name, name)) {
2889 uses->grp = (struct ly_mnode_grp *)mnode;
2890 return EXIT_SUCCESS;
2891 }
2892 }
2893 } else {
2894 /* in local tree hierarchy */
2895 for (mnode_aux = parent; mnode_aux; mnode_aux = mnode_aux->parent) {
2896 LY_TREE_FOR(mnode_aux->child, mnode) {
2897 if (mnode->nodetype == LY_NODE_GROUPING && !strcmp(mnode->name, name)) {
2898 uses->grp = (struct ly_mnode_grp *)mnode;
2899 return EXIT_SUCCESS;
2900 }
2901 }
2902 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02002903
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002904 /* search in top level of the current module */
2905 LY_TREE_FOR(module->data, mnode) {
2906 if (mnode->nodetype == LY_NODE_GROUPING && !strcmp(mnode->name, name)) {
2907 uses->grp = (struct ly_mnode_grp *)mnode;
2908 return EXIT_SUCCESS;
2909 }
2910 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02002911
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002912 /* search in top-level of included modules */
2913 for (i = 0; i < module->inc_size; i++) {
2914 LY_TREE_FOR(module->inc[i].submodule->data, mnode) {
2915 if (mnode->nodetype == LY_NODE_GROUPING && !strcmp(mnode->name, name)) {
2916 uses->grp = (struct ly_mnode_grp *)mnode;
2917 return EXIT_SUCCESS;
2918 }
2919 }
2920 }
2921 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02002922
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002923 /* not found, but no explicit error occured */
2924 return EXIT_SUCCESS;
Radek Krejci74705112015-06-05 10:25:44 +02002925}
2926
Radek Krejcif5be10f2015-06-16 13:29:36 +02002927static int
2928resolve_augment(struct ly_augment *aug, struct ly_mnode *parent, struct ly_module *module, unsigned int line)
2929{
2930 struct lyxml_elem *yin, *next, *sub;
2931 struct ly_mnode *mnode;
2932
2933 assert(module);
2934
2935 /* resolve target node */
2936 aug->target = resolve_schema_nodeid(aug->target_name, parent, module);
2937 if (!aug->target) {
2938 LOGVAL(VE_INARG, line, aug->target, "uses");
2939 return EXIT_FAILURE;
2940 }
2941
2942 if (!aug->child) {
2943 /* nothing to do */
2944 return EXIT_SUCCESS;
2945 }
2946
2947 yin = (struct lyxml_elem *)aug->child;
2948
2949 if (read_yin_common(module, aug->target, (struct ly_mnode *)aug, yin, OPT_CONFIG)) {
2950 return EXIT_FAILURE;
2951 }
2952
2953 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2954 if (!strcmp(sub->name, "container")) {
2955 mnode = read_yin_container(module, aug->target, sub, 1, NULL);
2956 } else if (!strcmp(sub->name, "leaf-list")) {
2957 mnode = read_yin_leaflist(module, aug->target, sub, 1);
2958 } else if (!strcmp(sub->name, "leaf")) {
2959 mnode = read_yin_leaf(module, aug->target, sub, 1);
2960 } else if (!strcmp(sub->name, "list")) {
2961 mnode = read_yin_list(module, aug->target, sub, 1, NULL);
2962 } else if (!strcmp(sub->name, "uses")) {
2963 mnode = read_yin_uses(module, aug->target, sub, 1, NULL);
2964 } else if (!strcmp(sub->name, "choice")) {
2965 mnode = read_yin_case(module, aug->target, sub, 1, NULL);
2966 } else if (!strcmp(sub->name, "case")) {
2967 mnode = read_yin_case(module, aug->target, sub, 1, NULL);
2968 } else if (!strcmp(sub->name, "anyxml")) {
2969 mnode = read_yin_anyxml(module, aug->target, sub, 1);
2970#if 0
2971 } else {
2972 LOGVAL(VE_INSTMT, LOGLINE(sub), sub->name);
2973 goto error;
2974#else
2975 } else {
2976 continue;
2977#endif
2978 }
2979
2980 if (!mnode) {
2981 return EXIT_FAILURE;
2982 }
2983
2984 lyxml_free_elem(module->ctx, sub);
2985
2986 /* the parent pointer will point to the augment node, but all
2987 * siblings pointers and possibly the child node in target does
2988 * not know about the augment and follow the standard schema tree
2989 * structure
2990 */
2991 mnode->parent = (struct ly_mnode *)aug;
2992 mnode = NULL;
2993 }
2994
2995 lyxml_free_elem(module->ctx, yin);
2996 aug->child = NULL;
2997
2998 return EXIT_SUCCESS;
2999}
3000
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003001int
3002resolve_uses(struct ly_mnode_uses *uses, unsigned int line)
Radek Krejci106efc02015-06-10 14:36:27 +02003003{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003004 struct ly_ctx *ctx;
3005 struct ly_mnode *mnode = NULL, *mnode_aux;
3006 struct ly_refine *rfn;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003007 struct ly_must *newmust;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003008 int i, j;
3009 uint8_t size;
Radek Krejci106efc02015-06-10 14:36:27 +02003010
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003011 /* copy the data nodes from grouping into the uses context */
3012 LY_TREE_FOR(uses->grp->child, mnode) {
3013 mnode_aux = ly_mnode_dup(uses->module, mnode, uses->flags, 1, line);
3014 if (!mnode_aux) {
3015 LOGVAL(VE_SPEC, line, "Copying data from grouping failed");
3016 return EXIT_FAILURE;
3017 }
3018 if (ly_mnode_addchild((struct ly_mnode *)uses, mnode_aux)) {
3019 ly_mnode_free(mnode_aux);
3020 return EXIT_FAILURE;
3021 }
3022 }
3023 ctx = uses->module->ctx;
Radek Krejci106efc02015-06-10 14:36:27 +02003024
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003025 /* apply refines */
3026 for (i = 0; i < uses->refine_size; i++) {
3027 rfn = &uses->refine[i];
Radek Krejcif5be10f2015-06-16 13:29:36 +02003028 mnode = resolve_schema_nodeid(rfn->target, (struct ly_mnode *)uses, uses->module);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003029 if (!mnode) {
3030 LOGVAL(VE_INARG, line, rfn->target, "uses");
3031 return EXIT_FAILURE;
3032 }
Radek Krejci106efc02015-06-10 14:36:27 +02003033
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003034 if (rfn->target_type && !(mnode->nodetype & rfn->target_type)) {
3035 LOGVAL(VE_SPEC, line, "refine substatements not applicable to the target-node");
3036 return EXIT_FAILURE;
3037 }
Radek Krejci106efc02015-06-10 14:36:27 +02003038
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003039 /* description on any nodetype */
3040 if (rfn->dsc) {
3041 lydict_remove(ctx, mnode->dsc);
3042 mnode->dsc = lydict_insert(ctx, rfn->dsc, 0);
3043 }
Radek Krejci106efc02015-06-10 14:36:27 +02003044
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003045 /* reference on any nodetype */
3046 if (rfn->ref) {
3047 lydict_remove(ctx, mnode->ref);
3048 mnode->ref = lydict_insert(ctx, rfn->ref, 0);
3049 }
Radek Krejci106efc02015-06-10 14:36:27 +02003050
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003051 /* config on any nodetype */
3052 if (rfn->flags & LY_NODE_CONFIG_MASK) {
3053 mnode->flags &= ~LY_NODE_CONFIG_MASK;
3054 mnode->flags |= (rfn->flags & LY_NODE_CONFIG_MASK);
3055 }
Radek Krejci106efc02015-06-10 14:36:27 +02003056
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003057 /* default value ... */
3058 if (rfn->mod.dflt) {
3059 if (mnode->nodetype == LY_NODE_LEAF) {
3060 /* leaf */
3061 lydict_remove(ctx, ((struct ly_mnode_leaf *)mnode)->dflt);
3062 ((struct ly_mnode_leaf *)mnode)->dflt = lydict_insert(ctx, rfn->mod.dflt, 0);
3063 } else if (mnode->nodetype == LY_NODE_CHOICE) {
3064 /* choice */
Radek Krejcif5be10f2015-06-16 13:29:36 +02003065 ((struct ly_mnode_choice *)mnode)->dflt = resolve_schema_nodeid(rfn->mod.dflt, mnode, mnode->module);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003066 if (!((struct ly_mnode_choice *)mnode)->dflt) {
3067 LOGVAL(VE_INARG, line, rfn->mod.dflt, "default");
3068 return EXIT_FAILURE;
3069 }
3070 }
3071 }
Radek Krejci106efc02015-06-10 14:36:27 +02003072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003073 /* mandatory on leaf, anyxml or choice */
3074 if (mnode->nodetype & (LY_NODE_LEAF | LY_NODE_ANYXML | LY_NODE_CHOICE)) {
3075 if (rfn->flags & LY_NODE_MAND_FALSE) {
3076 /* erase mandatory true flag, we don't use false flag in schema nodes */
3077 mnode->flags &= ~LY_NODE_MAND_TRUE;
3078 } else if (rfn->flags & LY_NODE_MAND_TRUE) {
3079 /* set mandatory true flag */
3080 mnode->flags |= LY_NODE_MAND_TRUE;
3081 }
3082 }
Radek Krejci106efc02015-06-10 14:36:27 +02003083
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003084 /* presence on container */
3085 if ((mnode->nodetype & LY_NODE_CONTAINER) && rfn->mod.presence) {
3086 lydict_remove(ctx, ((struct ly_mnode_container *)mnode)->presence);
3087 ((struct ly_mnode_container *)mnode)->presence = lydict_insert(ctx, rfn->mod.presence, 0);
3088 }
Radek Krejci106efc02015-06-10 14:36:27 +02003089
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003090 /* min/max-elements on list or leaf-list */
3091 if (mnode->nodetype & (LY_NODE_LEAFLIST | LY_NODE_LIST)) {
3092 /* magic - bit 3 in flags means min set, bit 4 says max set */
3093 if (rfn->flags & 0x04) {
3094 ((struct ly_mnode_list *)mnode)->min = rfn->mod.list.min;
3095 }
3096 if (rfn->flags & 0x08) {
3097 ((struct ly_mnode_list *)mnode)->max = rfn->mod.list.max;
3098 }
3099 }
Radek Krejci106efc02015-06-10 14:36:27 +02003100
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003101 /* must in leaf, leaf-list, list, container or anyxml */
3102 if (rfn->must_size) {
3103 size = ((struct ly_mnode_leaf *)mnode)->must_size + rfn->must_size;
3104 newmust = realloc(((struct ly_mnode_leaf *)mnode)->must, size * sizeof *rfn->must);
3105 if (!newmust) {
3106 LOGMEM;
3107 return EXIT_FAILURE;
3108 }
3109 for (i = 0, j = ((struct ly_mnode_leaf *)mnode)->must_size; i < rfn->must_size; i++, j++) {
3110 newmust[j].cond = lydict_insert(ctx, rfn->must[i].cond, 0);
3111 newmust[j].dsc = lydict_insert(ctx, rfn->must[i].dsc, 0);
3112 newmust[j].ref = lydict_insert(ctx, rfn->must[i].ref, 0);
3113 newmust[j].eapptag = lydict_insert(ctx, rfn->must[i].eapptag, 0);
3114 newmust[j].emsg = lydict_insert(ctx, rfn->must[i].emsg, 0);
3115 }
Radek Krejci106efc02015-06-10 14:36:27 +02003116
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003117 ((struct ly_mnode_leaf *)mnode)->must = newmust;
3118 ((struct ly_mnode_leaf *)mnode)->must_size = size;
3119 }
3120 }
Radek Krejci106efc02015-06-10 14:36:27 +02003121
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003122 /* apply augments */
3123 for (i = 0; i < uses->augment_size; i++) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02003124 if (resolve_augment(&uses->augment[i], (struct ly_mnode *)uses, uses->module, line)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003125 goto error;
3126 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003127 }
Radek Krejci106efc02015-06-10 14:36:27 +02003128
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003129 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02003130
3131error:
3132
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003133 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02003134}
Radek Krejci74705112015-06-05 10:25:44 +02003135
3136/*
3137 * resolve - referenced grouping should be bounded to the namespace (resolved)
3138 * only when uses does not appear in grouping. In a case of grouping's uses,
3139 * we just get information but we do not apply augment or refine to it.
3140 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003141static struct ly_mnode *
3142read_yin_uses(struct ly_module *module,
3143 struct ly_mnode *parent, struct lyxml_elem *node, int resolve, struct mnode_list **unres)
Radek Krejci74705112015-06-05 10:25:44 +02003144{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003145 struct lyxml_elem *sub, *next;
3146 struct ly_mnode *retval;
3147 struct ly_mnode_uses *uses;
3148 struct mnode_list *unres_new;
3149 const char *value;
3150 int c_ref = 0, c_aug = 0;
3151 int r;
Radek Krejci74705112015-06-05 10:25:44 +02003152
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003153 uses = calloc(1, sizeof *uses);
3154 uses->nodetype = LY_NODE_USES;
3155 uses->prev = (struct ly_mnode *)uses;
3156 retval = (struct ly_mnode *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02003157
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003158 GETVAL(value, node, "name");
3159 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02003160
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003161 if (read_yin_common(module, parent, retval, node, OPT_MODULE | (resolve ? OPT_INHERIT : 0))) {
3162 goto error;
3163 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02003164
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003165 /* get other properties of uses */
3166 LY_TREE_FOR_SAFE(node->child, next, sub) {
3167 if (!strcmp(sub->name, "refine")) {
3168 c_ref++;
3169 } else if (!strcmp(sub->name, "augment")) {
3170 c_aug++;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003171#if 0
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003172 } else {
3173 LOGVAL(VE_INSTMT, LOGLINE(sub), sub->name);
3174 goto error;
Radek Krejcifac63ba2015-06-10 14:48:40 +02003175#else
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003176 } else {
3177 lyxml_free_elem(module->ctx, sub);
Radek Krejci3bde87f2015-06-05 16:51:58 +02003178#endif
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003179 }
3180 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003181
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003182 /* process properties with cardinality 0..n */
3183 if (c_ref) {
3184 uses->refine = calloc(c_ref, sizeof *uses->refine);
3185 }
3186 if (c_aug) {
3187 uses->augment = calloc(c_aug, sizeof *uses->augment);
3188 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003189
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003190 LY_TREE_FOR_SAFE(node->child, next, sub) {
3191 if (!strcmp(sub->name, "refine")) {
3192 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size]);
3193 uses->refine_size++;
3194 } else { /* augment */
3195 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size]);
3196 uses->augment_size++;
3197 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003198
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003199 if (r) {
3200 goto error;
3201 }
3202 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003203
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003204 if (find_grouping(parent, uses, LOGLINE(node))) {
3205 goto error;
3206 }
3207 if (!uses->grp) {
3208 LOGVRB("Unresolved uses of \"%s\" (line %d), trying to resolve it later", uses->name, LOGLINE(node));
3209 unres_new = calloc(1, sizeof *unres_new);
3210 if (*unres) {
3211 unres_new->next = *unres;
3212 }
3213 unres_new->mnode = retval;
3214 unres_new->line = LOGLINE(node);
Radek Krejci74705112015-06-05 10:25:44 +02003215
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003216 /* put it at the beginning of the unresolved list */
3217 *unres = unres_new;
3218 }
Radek Krejci74705112015-06-05 10:25:44 +02003219
Radek Krejci368c38f2015-06-15 15:09:55 +02003220 if (parent && ly_mnode_addchild(parent, retval)) {
3221 goto error;
3222 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02003223
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003224 if (resolve) {
3225 /* inherit config flag */
3226 if (parent) {
3227 retval->flags |= parent->flags & LY_NODE_CONFIG_MASK;
3228 } else {
3229 /* default config is true */
3230 retval->flags |= LY_NODE_CONFIG_W;
3231 }
3232 }
Radek Krejcib388c152015-06-04 17:03:03 +02003233
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003234 if (resolve && uses->grp) {
3235 /* copy the data nodes from grouping into the uses context */
3236 if (resolve_uses(uses, LOGLINE(node))) {
3237 goto error;
3238 }
3239 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02003240
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003241 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02003242
3243error:
3244
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003245 ly_mnode_free(retval);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02003246
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003247 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02003248}
3249
Radek Krejciefaeba32015-05-27 14:30:57 +02003250/* common code for yin_read_module() and yin_read_submodule() */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003251static int
3252read_sub_module(struct ly_module *module, struct lyxml_elem *yin)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003253{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003254 struct ly_ctx *ctx = module->ctx;
3255 struct ly_submodule *submodule = (struct ly_submodule *)module;
3256 struct lyxml_elem *next, *node, *child, root, grps, rpcs, notifs;
3257 struct ly_mnode *mnode = NULL;
3258 struct mnode_list *unres = NULL, *unres_next; /* unresolved uses */
3259 const char *value;
Radek Krejcif5be10f2015-06-16 13:29:36 +02003260 int c_imp = 0, c_rev = 0, c_tpdf = 0, c_ident = 0, c_inc = 0, c_aug = 0; /* counters */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003261 int r;
Michal Vasko38d01f72015-06-15 09:41:06 +02003262 int i;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003263 int belongsto_flag = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003264
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003265 /* init */
3266 memset(&root, 0, sizeof root);
3267 memset(&grps, 0, sizeof grps);
3268 memset(&rpcs, 0, sizeof rpcs);
Michal Vasko0ea41032015-06-16 08:53:55 +02003269 memset(&notifs, 0, sizeof notifs);
Radek Krejcie0674f82015-06-15 13:58:51 +02003270
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003271 /*
3272 * in the first run, we process elements with cardinality of 1 or 0..1 and
3273 * count elements with cardinality 0..n. Data elements (choices, containers,
3274 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
3275 * need have all top-level and groupings already prepared at that time. In
3276 * the middle loop, we process other elements with carinality of 0..n since
3277 * we need to allocate arrays to store them.
3278 */
3279 LY_TREE_FOR_SAFE(yin->child, next, node) {
3280 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
3281 lyxml_free_elem(ctx, node);
3282 continue;
3283 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003285 if (!module->type && !strcmp(node->name, "namespace")) {
3286 if (module->ns) {
3287 LOGVAL(VE_TOOMANY, LOGLINE(node), node->name, yin->name);
3288 goto error;
3289 }
3290 GETVAL(value, node, "uri");
3291 module->ns = lydict_insert(ctx, value, strlen(value));
3292 lyxml_free_elem(ctx, node);
3293 } else if (!module->type && !strcmp(node->name, "prefix")) {
3294 if (module->prefix) {
3295 LOGVAL(VE_TOOMANY, LOGLINE(node), node->name, yin->name);
3296 goto error;
3297 }
3298 GETVAL(value, node, "value");
3299 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(node), module, NULL)) {
3300 goto error;
3301 }
3302 module->prefix = lydict_insert(ctx, value, strlen(value));
3303 lyxml_free_elem(ctx, node);
3304 } else if (module->type && !strcmp(node->name, "belongs-to")) {
3305 if (belongsto_flag) {
3306 LOGVAL(VE_TOOMANY, LOGLINE(node), node->name, yin->name);
3307 goto error;
3308 }
3309 belongsto_flag = 1;
3310 GETVAL(value, node, "module");
3311 while (submodule->belongsto->type) {
3312 submodule->belongsto = ((struct ly_submodule *)submodule->belongsto)->belongsto;
3313 }
3314 if (value != submodule->belongsto->name) {
3315 LOGVAL(VE_INARG, LOGLINE(node), value, node->name);
3316 goto error;
3317 }
Radek Krejcif3886932015-06-04 17:36:06 +02003318
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003319 /* get the prefix substatement, start with checks */
3320 if (!node->child) {
3321 LOGVAL(VE_MISSSTMT2, LOGLINE(node), "prefix", node->name);
3322 goto error;
3323 } else if (strcmp(node->child->name, "prefix")) {
3324 LOGVAL(VE_INSTMT, LOGLINE(node->child), node->child->name);
3325 goto error;
3326 } else if (node->child->next) {
3327 LOGVAL(VE_INSTMT, LOGLINE(node->child->next), node->child->next->name);
3328 goto error;
3329 }
3330 /* and now finally get the value */
3331 GETVAL(value, node->child, "value");
3332 /* check here differs from a generic prefix check, since this prefix
3333 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02003334 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003335 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(node->child), NULL, NULL)) {
3336 goto error;
3337 }
3338 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02003339
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003340 /* we are done with belongs-to */
3341 lyxml_free_elem(ctx, node);
3342 } else if (!strcmp(node->name, "import")) {
3343 c_imp++;
3344 } else if (!strcmp(node->name, "revision")) {
3345 c_rev++;
3346 } else if (!strcmp(node->name, "typedef")) {
3347 c_tpdf++;
3348 } else if (!strcmp(node->name, "identity")) {
3349 c_ident++;
3350 } else if (!strcmp(node->name, "include")) {
3351 c_inc++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02003352 } else if (!strcmp(node->name, "augment")) {
3353 c_aug++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003354
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003355 /* data statements */
3356 } else if (!strcmp(node->name, "container") ||
3357 !strcmp(node->name, "leaf-list") ||
3358 !strcmp(node->name, "leaf") ||
3359 !strcmp(node->name, "list") ||
3360 !strcmp(node->name, "choice") ||
3361 !strcmp(node->name, "uses") ||
3362 !strcmp(node->name, "anyxml")) {
3363 lyxml_unlink_elem(node);
3364 lyxml_add_child(&root, node);
3365 } else if (!strcmp(node->name, "grouping")) {
3366 /* keep groupings separated and process them before other data statements */
3367 lyxml_unlink_elem(node);
3368 lyxml_add_child(&grps, node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003369
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003370 /* optional statements */
3371 } else if (!strcmp(node->name, "description")) {
3372 if (module->dsc) {
3373 LOGVAL(VE_TOOMANY, LOGLINE(node), node->name, yin->name);
3374 goto error;
3375 }
3376 module->dsc = read_yin_subnode(ctx, node, "text");
3377 lyxml_free_elem(ctx, node);
3378 if (!module->dsc) {
3379 goto error;
3380 }
3381 } else if (!strcmp(node->name, "reference")) {
3382 if (module->ref) {
3383 LOGVAL(VE_TOOMANY, LOGLINE(node), node->name, yin->name);
3384 goto error;
3385 }
3386 module->ref = read_yin_subnode(ctx, node, "text");
3387 lyxml_free_elem(ctx, node);
3388 if (!module->ref) {
3389 goto error;
3390 }
3391 } else if (!strcmp(node->name, "organization")) {
3392 if (module->org) {
3393 LOGVAL(VE_TOOMANY, LOGLINE(node), node->name, yin->name);
3394 goto error;
3395 }
3396 module->org = read_yin_subnode(ctx, node, "text");
3397 lyxml_free_elem(ctx, node);
3398 if (!module->org) {
3399 goto error;
3400 }
3401 } else if (!strcmp(node->name, "contact")) {
3402 if (module->contact) {
3403 LOGVAL(VE_TOOMANY, LOGLINE(node), node->name, yin->name);
3404 goto error;
3405 }
3406 module->contact = read_yin_subnode(ctx, node, "text");
3407 lyxml_free_elem(ctx, node);
3408 if (!module->contact) {
3409 goto error;
3410 }
3411 } else if (!strcmp(node->name, "yang-version")) {
3412 /* TODO: support YANG 1.1 ? */
3413 if (module->version) {
3414 LOGVAL(VE_TOOMANY, LOGLINE(node), node->name, yin->name);
3415 goto error;
3416 }
3417 GETVAL(value, node, "value");
3418 if (strcmp(value, "1")) {
3419 LOGVAL(VE_INARG, LOGLINE(node), value, "yang-version");
3420 goto error;
3421 }
3422 module->version = 1;
3423 lyxml_free_elem(ctx, node);
Michal Vasko38d01f72015-06-15 09:41:06 +02003424
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003425 /* rpcs & notifications */
Michal Vasko38d01f72015-06-15 09:41:06 +02003426 } else if (!strcmp(node->name, "rpc")) {
3427 lyxml_unlink_elem(node);
3428 lyxml_add_child(&rpcs, node);
Michal Vasko0ea41032015-06-16 08:53:55 +02003429 } else if (!strcmp(node->name, "notification")) {
3430 lyxml_unlink_elem(node);
3431 lyxml_add_child(&notifs, node);
Radek Krejci1e3f8902015-06-03 11:00:11 +02003432#if 0
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003433 } else {
3434 LOGVAL(VE_INSTMT, LOGLINE(node), node->name);
3435 goto error;
Radek Krejci8eaf9bd2015-06-04 11:05:18 +02003436#else
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003437 } else {
3438 continue;
Radek Krejci1e3f8902015-06-03 11:00:11 +02003439#endif
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003440 }
3441 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003442
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003443 if (!submodule) {
3444 /* check for mandatory statements */
3445 if (!module->ns) {
3446 LOGVAL(VE_MISSSTMT2, LOGLINE(yin), "namespace", "module");
3447 goto error;
3448 }
3449 if (!module->prefix) {
3450 LOGVAL(VE_MISSSTMT2, LOGLINE(yin), "prefix", "module");
3451 goto error;
3452 }
3453 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02003454
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003455 /* allocate arrays for elements with cardinality of 0..n */
3456 if (c_imp) {
3457 module->imp = calloc(c_imp, sizeof *module->imp);
3458 }
3459 if (c_rev) {
3460 module->rev = calloc(c_rev, sizeof *module->rev);
3461 }
3462 if (c_tpdf) {
3463 module->tpdf = calloc(c_tpdf, sizeof *module->tpdf);
3464 }
3465 if (c_ident) {
3466 module->ident = calloc(c_ident, sizeof *module->ident);
3467 }
3468 if (c_inc) {
3469 module->inc = calloc(c_inc, sizeof *module->inc);
3470 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02003471 if (c_aug) {
3472 module->augment = calloc(c_aug, sizeof *module->augment);
3473 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003474
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003475 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3476 LY_TREE_FOR_SAFE(yin->child, next, node) {
3477 if (!strcmp(node->name, "import")) {
3478 r = fill_yin_import(module, node, &module->imp[module->imp_size]);
3479 module->imp_size++;
3480 if (r) {
3481 goto error;
3482 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003484 /* check duplicities in imported modules */
3485 for (i = 0; i < module->imp_size - 1; i++) {
3486 if (!strcmp(module->imp[i].module->name, module->imp[module->imp_size - 1].module->name)) {
3487 LOGVAL(VE_SPEC, LOGLINE(node), "Importing module \"%s\" repeatedly.", module->imp[i].module->name);
3488 goto error;
3489 }
3490 }
3491 } else if (!strcmp(node->name, "include")) {
3492 r = fill_yin_include(module, node, &module->inc[module->inc_size]);
3493 module->inc_size++;
3494 if (r) {
3495 goto error;
3496 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003497
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003498 /* check duplications in include submodules */
3499 for (i = 0; i < module->inc_size - 1; i++) {
3500 if (!strcmp(module->inc[i].submodule->name, module->inc[module->inc_size - 1].submodule->name)) {
3501 LOGVAL(VE_SPEC, LOGLINE(node), "Importing module \"%s\" repeatedly.",
3502 module->inc[i].submodule->name);
3503 goto error;
3504 }
3505 }
3506 } else if (!strcmp(node->name, "revision")) {
3507 GETVAL(value, node, "date");
3508 if (check_date(value, LOGLINE(node))) {
3509 goto error;
3510 }
3511 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
3512 /* check uniqueness of the revision date - not required by RFC */
3513 for (i = 0; i < module->rev_size; i++) {
3514 if (!strcmp(value, module->rev[i].date)) {
3515 LOGVAL(VE_INARG, LOGLINE(node), value, node->name);
3516 LOGVAL(VE_SPEC, 0, "Revision is not unique.");
3517 }
3518 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003519
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003520 LY_TREE_FOR(node->child, child) {
3521 if (!strcmp(child->name, "description")) {
3522 if (module->rev[module->rev_size].dsc) {
3523 LOGVAL(VE_TOOMANY, LOGLINE(node), child->name, node->name);
3524 goto error;
3525 }
3526 module->rev[module->rev_size].dsc = read_yin_subnode(ctx, child, "text");
3527 if (!module->rev[module->rev_size].dsc) {
3528 goto error;
3529 }
3530 } else if (!strcmp(child->name, "reference")) {
3531 if (module->rev[module->rev_size].ref) {
3532 LOGVAL(VE_TOOMANY, LOGLINE(node), child->name, node->name);
3533 goto error;
3534 }
3535 module->rev[module->rev_size].ref = read_yin_subnode(ctx, child, "text");
3536 if (!module->rev[module->rev_size].ref) {
3537 goto error;
3538 }
3539 } else {
3540 LOGVAL(VE_INSTMT, LOGLINE(child), child->name);
3541 goto error;
3542 }
3543 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003544
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003545 /* keep the latest revision at position 0 */
3546 if (module->rev_size && strcmp(module->rev[module->rev_size].date, module->rev[0].date) > 0) {
3547 /* switch their position */
3548 value = strdup(module->rev[0].date);
3549 memcpy(module->rev[0].date, module->rev[module->rev_size].date, LY_REV_SIZE - 1);
3550 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
3551 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02003552
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003553 if (module->rev[0].dsc != module->rev[module->rev_size].dsc) {
3554 value = module->rev[0].dsc;
3555 module->rev[0].dsc = module->rev[module->rev_size].dsc;
3556 module->rev[module->rev_size].dsc = value;
3557 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003558
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003559 if (module->rev[0].ref != module->rev[module->rev_size].ref) {
3560 value = module->rev[0].ref;
3561 module->rev[0].ref = module->rev[module->rev_size].ref;
3562 module->rev[module->rev_size].ref = value;
3563 }
3564 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003565
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003566 module->rev_size++;
3567 } else if (!strcmp(node->name, "typedef")) {
3568 r = fill_yin_typedef(module, NULL, node, &module->tpdf[module->tpdf_size]);
3569 module->tpdf_size++;
Radek Krejci25d782a2015-05-22 15:03:23 +02003570
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003571 if (r) {
3572 goto error;
3573 }
3574 } else if (!strcmp(node->name, "identity")) {
3575 r = fill_yin_identity(module, node, &module->ident[module->ident_size]);
3576 module->ident_size++;
Radek Krejci6793db02015-05-22 17:49:54 +02003577
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003578 if (r) {
3579 goto error;
3580 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02003581 } else if (!strcmp(node->name, "augment")) {
3582 r = fill_yin_augment(module, NULL, node, &module->augment[module->augment_size]);
3583 module->augment_size++;
3584
3585 if (r) {
3586 goto error;
3587 }
3588
3589 /* node is reconnected into the augment, so we have to skip its free at the end of the loop */
3590 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003591 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003592
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003593 lyxml_free_elem(ctx, node);
3594 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003595
Radek Krejcif5be10f2015-06-16 13:29:36 +02003596 /* process data nodes. Start with groupings to allow uses
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003597 * refer to them
3598 */
3599 LY_TREE_FOR_SAFE(grps.child, next, node) {
3600 mnode = read_yin_grouping(module, NULL, node, 0, &unres);
3601 lyxml_free_elem(ctx, node);
Radek Krejci74705112015-06-05 10:25:44 +02003602
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003603 if (!mnode) {
3604 goto error;
3605 }
Radek Krejci74705112015-06-05 10:25:44 +02003606
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003607 /* include data element */
3608 if (module->data) {
3609 module->data->prev->next = mnode;
3610 mnode->prev = module->data->prev;
3611 module->data->prev = mnode;
3612 } else {
3613 module->data = mnode;
3614 }
3615 }
3616 while (unres) {
3617 if (find_grouping(unres->mnode->parent, (struct ly_mnode_uses *)unres->mnode, unres->line)) {
3618 goto error;
3619 }
3620 if (!((struct ly_mnode_uses *)unres->mnode)->grp) {
3621 LOGVAL(VE_INARG, unres->line, unres->mnode->name, "uses");
3622 goto error;
3623 }
3624 unres_next = unres->next;
3625 free(unres);
3626 unres = unres_next;
3627 }
Radek Krejci74705112015-06-05 10:25:44 +02003628
Radek Krejcif5be10f2015-06-16 13:29:36 +02003629 /* parse data nodes, ... */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003630 LY_TREE_FOR_SAFE(root.child, next, node) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02003631
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003632 if (!strcmp(node->name, "container")) {
3633 mnode = read_yin_container(module, NULL, node, 1, &unres);
3634 } else if (!strcmp(node->name, "leaf-list")) {
3635 mnode = read_yin_leaflist(module, NULL, node, 1);
3636 } else if (!strcmp(node->name, "leaf")) {
3637 mnode = read_yin_leaf(module, NULL, node, 1);
3638 } else if (!strcmp(node->name, "list")) {
3639 mnode = read_yin_list(module, NULL, node, 1, &unres);
3640 } else if (!strcmp(node->name, "choice")) {
3641 mnode = read_yin_choice(module, NULL, node, 1, &unres);
3642 } else if (!strcmp(node->name, "uses")) {
3643 mnode = read_yin_uses(module, NULL, node, 1, &unres);
3644 } else if (!strcmp(node->name, "anyxml")) {
3645 mnode = read_yin_anyxml(module, NULL, node, 1);
3646 }
3647 lyxml_free_elem(ctx, node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003648
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003649 if (!mnode) {
3650 goto error;
3651 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003652
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003653 /* include data element */
3654 if (module->data) {
3655 module->data->prev->next = mnode;
3656 mnode->prev = module->data->prev;
3657 module->data->prev = mnode;
3658 } else {
3659 module->data = mnode;
3660 }
3661 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02003662
3663 /* ... rpcs ... */
3664 LY_TREE_FOR_SAFE(rpcs.child, next, node) {
3665 mnode = read_yin_rpc(module, NULL, node, 0, &unres);
3666 lyxml_free_elem(ctx, node);
3667
3668 if (!mnode) {
3669 goto error;
3670 }
3671
3672 /* include rpc element */
3673 if (module->rpc) {
3674 module->rpc->prev->next = mnode;
3675 mnode->prev = module->rpc->prev;
3676 module->rpc->prev = mnode;
3677 } else {
3678 module->rpc = mnode;
3679 }
3680 }
3681
3682 /* ... and notifications */
3683 LY_TREE_FOR_SAFE(notifs.child, next, node) {
3684 mnode = read_yin_notif(module, NULL, node, 0, &unres);
3685 lyxml_free_elem(ctx, node);
3686
3687 if (!mnode) {
3688 goto error;
3689 }
3690
3691 /* include notification element */
3692 if (module->notif) {
3693 module->notif->prev->next = mnode;
3694 mnode->prev = module->notif->prev;
3695 module->notif->prev = mnode;
3696 } else {
3697 module->notif = mnode;
3698 }
3699 }
3700
3701 /* and now try to resolve unresolved uses, if any */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003702 while (unres) {
3703 /* find referenced grouping */
3704 if (find_grouping(unres->mnode->parent, (struct ly_mnode_uses *)unres->mnode, unres->line)) {
3705 goto error;
3706 }
3707 if (!((struct ly_mnode_uses *)unres->mnode)->grp) {
3708 LOGVAL(VE_INARG, unres->line, unres->mnode->name, "uses");
3709 goto error;
3710 }
Radek Krejci74705112015-06-05 10:25:44 +02003711
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003712 /* resolve uses by copying grouping content under the uses */
3713 if (resolve_uses((struct ly_mnode_uses *)unres->mnode, unres->line)) {
3714 goto error;
3715 }
Radek Krejci74705112015-06-05 10:25:44 +02003716
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003717 unres_next = unres->next;
3718 free(unres);
3719 unres = unres_next;
3720 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003721
Radek Krejcif5be10f2015-06-16 13:29:36 +02003722 /* and finally apply augments */
3723 for (i = 0; i < module->augment_size; i++) {
3724 if (resolve_augment(&module->augment[i], NULL, module, 0)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02003725 goto error;
3726 }
Michal Vasko0ea41032015-06-16 08:53:55 +02003727 }
3728
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003729 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02003730
3731error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003732 /* cleanup */
3733 while (root.child) {
3734 lyxml_free_elem(module->ctx, root.child);
3735 }
3736 while (grps.child) {
3737 lyxml_free_elem(module->ctx, grps.child);
3738 }
3739 while (rpcs.child) {
Michal Vasko38d01f72015-06-15 09:41:06 +02003740 lyxml_free_elem(module->ctx, rpcs.child);
3741 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003742
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003743 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02003744}
3745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003746struct ly_submodule *
3747yin_read_submodule(struct ly_module *module, const char *data)
Radek Krejciefaeba32015-05-27 14:30:57 +02003748{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003749 struct lyxml_elem *yin;
3750 struct ly_submodule *submodule = NULL;
3751 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02003752
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003753 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02003754
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003755 yin = lyxml_read(module->ctx, data, 0);
3756 if (!yin) {
3757 return NULL;
3758 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003759
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003760 /* check root element */
3761 if (!yin->name || strcmp(yin->name, "submodule")) {
3762 LOGVAL(VE_INSTMT, LOGLINE(yin), yin->name);
3763 goto error;
3764 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003765
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003766 GETVAL(value, yin, "name");
3767 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
3768 goto error;
3769 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003770
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003771 submodule = calloc(1, sizeof *submodule);
3772 if (!submodule) {
3773 LOGMEM;
3774 goto error;
3775 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003776
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003777 submodule->ctx = module->ctx;
3778 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
3779 submodule->type = 1;
3780 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02003781
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003782 LOGVRB("reading submodule %s", submodule->name);
3783 if (read_sub_module((struct ly_module *)submodule, yin)) {
3784 goto error;
3785 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003786
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003787 /* cleanup */
3788 lyxml_free_elem(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02003789
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003790 LOGVRB("submodule %s successfully parsed", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02003791
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003792 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02003793
3794error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003795 /* cleanup */
3796 lyxml_free_elem(module->ctx, yin);
3797 ly_submodule_free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02003798
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003799 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02003800}
3801
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003802struct ly_module *
3803yin_read_module(struct ly_ctx *ctx, const char *data)
Radek Krejciefaeba32015-05-27 14:30:57 +02003804{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003805 struct lyxml_elem *yin;
3806 struct ly_module *module = NULL, **newlist = NULL;
3807 const char *value;
3808 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02003809
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003810 yin = lyxml_read(ctx, data, 0);
3811 if (!yin) {
3812 return NULL;
3813 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003814
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003815 /* check root element */
3816 if (!yin->name || strcmp(yin->name, "module")) {
3817 LOGVAL(VE_INSTMT, LOGLINE(yin), yin->name);
3818 goto error;
3819 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003820
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003821 GETVAL(value, yin, "name");
3822 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
3823 goto error;
3824 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003825
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003826 module = calloc(1, sizeof *module);
3827 if (!module) {
3828 LOGMEM;
3829 goto error;
3830 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003831
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003832 module->ctx = ctx;
3833 module->name = lydict_insert(ctx, value, strlen(value));
3834 module->type = 0;
Radek Krejciefaeba32015-05-27 14:30:57 +02003835
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003836 LOGVRB("reading module %s", module->name);
3837 if (read_sub_module(module, yin)) {
3838 goto error;
3839 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003840
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003841 /* add to the context's list of modules */
3842 if (ctx->models.used == ctx->models.size) {
3843 newlist = realloc(ctx->models.list, ctx->models.size * 2);
3844 if (!newlist) {
3845 LOGMEM;
3846 goto error;
3847 }
3848 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
3849 newlist[i] = NULL;
3850 }
3851 ctx->models.size *= 2;
3852 ctx->models.list = newlist;
3853 }
3854 for (i = 0; ctx->models.list[i]; i++) {
3855 /* check name (name/revision) and namespace uniqueness */
3856 if (!strcmp(ctx->models.list[i]->name, module->name)) {
3857 if (!ctx->models.list[i]->rev_size && !module->rev_size) {
3858 /* both data models are same, with no revision specified */
3859 LOGERR(LY_EINVAL, "Module \"%s\" (no revision in either of them specified) already in context.",
3860 module->name);
3861 goto error;
3862 } else if (!ctx->models.list[i]->rev_size || !module->rev_size) {
3863 /* one of the models does not have a revision, so they differs */
3864 continue;
3865 } else {
3866 /* both models have a revision statement which we have to
3867 * compare, revision at position 0 is the last revision
3868 */
3869 if (!strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
3870 /* we have the same modules */
3871 LOGERR(LY_EINVAL, "Module \"%s\", revision %s already in context.", module->name,
3872 module->rev[0].date);
3873 goto error;
3874 }
3875 }
3876 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
3877 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\"",
3878 ctx->models.list[i]->name, module->name, module->ns);
3879 goto error;
3880 }
3881 }
3882 ctx->models.list[i] = module;
3883 ctx->models.used++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003884
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003885 /* cleanup */
3886 lyxml_free_elem(ctx, yin);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003887
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003888 LOGVRB("module %s successfully parsed", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003889
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003890 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003891
3892error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003893 /* cleanup */
3894 lyxml_free_elem(ctx, yin);
3895 ly_module_free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003896
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003897 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003898}