blob: 822e505149021ee33784c39828970e286e2d18fd [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 *
Radek Krejci54f6fb32016-02-24 12:56:39 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
Michal Vasko8de098c2016-02-26 10:00:25 +010011 *
Radek Krejci54f6fb32016-02-24 12:56:39 +010012 * https://opensource.org/licenses/BSD-3-Clause
Radek Krejcida04f4a2015-05-21 12:54:09 +020013 */
14
Radek Krejci812b10a2015-05-28 16:48:25 +020015#include <assert.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020016#include <ctype.h>
Radek Krejci8b4f23c2015-06-02 16:09:25 +020017#include <errno.h>
18#include <limits.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020019#include <stdint.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020020#include <stdlib.h>
21#include <string.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020022#include <stddef.h>
Michal Vasko69068852015-07-13 14:34:31 +020023#include <sys/types.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020024
Radek Krejci998a0b82015-08-17 13:14:36 +020025#include "libyang.h"
26#include "common.h"
27#include "context.h"
Radek Krejci41912fe2015-10-22 10:22:12 +020028#include "dict_private.h"
Michal Vaskofcdac172015-10-07 09:35:05 +020029#include "xpath.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020030#include "parser.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020031#include "resolve.h"
32#include "tree_internal.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020033#include "xml_internal.h"
Radek Krejciefdd0ce2015-05-26 16:48:29 +020034
Radek Krejciadb57612016-02-16 13:34:34 +010035#define GETVAL(value, node, arg) \
36 value = lyxml_get_attr(node, arg, NULL); \
37 if (!value) { \
Radek Krejci48464ed2016-03-17 15:44:09 +010038 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, arg, node->name); \
Radek Krejciadb57612016-02-16 13:34:34 +010039 goto error; \
Michal Vasko2d710f32016-02-05 12:29:21 +010040 }
Radek Krejcice7fb782015-05-29 16:52:34 +020041
Michal Vaskoe022a562016-09-27 14:24:15 +020042#define OPT_IDENT 0x01
43#define OPT_CFG_PARSE 0x02
44#define OPT_CFG_INHERIT 0x04
45#define OPT_CFG_IGNORE 0x08
46#define OPT_MODULE 0x10
Radek Krejci07d0fb92017-01-13 14:11:05 +010047static int read_yin_common(struct lys_module *, struct lys_node *, void *, LYEXT_PAR, struct lyxml_elem *, int,
48 struct unres_schema *);
Radek Krejcib388c152015-06-04 17:03:03 +020049
Radek Krejcib8048692015-08-05 13:36:34 +020050static struct lys_node *read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020051 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020052static struct lys_node *read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020053 int valid_config, struct unres_schema *unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +020054static struct lys_node *read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020055 LYS_NODE type, int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020056static struct lys_node *read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020057 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020058static struct lys_node *read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020059 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020060static struct lys_node *read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020061 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020062static struct lys_node *read_yin_list(struct lys_module *module,struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020063 int valid_config, struct unres_schema *unres);
Radek Krejcia9544502015-08-14 08:24:29 +020064static struct lys_node *read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci3440cc52016-06-23 17:03:59 +020065 struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020066static struct lys_node *read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020067 int valid_config, struct unres_schema *unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +020068static struct lys_node *read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020069 struct unres_schema *unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +020070static struct lys_node *read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020071 struct unres_schema *unres);
Radek Krejci5323b492017-01-16 15:40:11 +010072static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres);
Radek Krejci74705112015-06-05 10:25:44 +020073
Radek Krejci07d0fb92017-01-13 14:11:05 +010074/*
75 * yin - the provided XML subtree is unlinked
Radek Krejci2b999ac2017-01-18 16:22:12 +010076 * ext - pointer to the storage in the parent structure to be able to update its location after realloc
Radek Krejci07d0fb92017-01-13 14:11:05 +010077 */
78int
79lyp_yin_fill_ext(void *parent, LYEXT_PAR parent_type, LYEXT_SUBSTMT substmt, uint8_t substmt_index,
Radek Krejci2b999ac2017-01-18 16:22:12 +010080 struct lys_module *module, struct lyxml_elem *yin, struct lys_ext_instance ***ext,
81 uint8_t ext_index, struct unres_schema *unres)
Radek Krejci07d0fb92017-01-13 14:11:05 +010082{
83 struct unres_ext *info;
84
85 info = malloc(sizeof *info);
86 lyxml_unlink(module->ctx, yin);
87 info->data.yin = yin;
88 info->datatype = LYS_IN_YIN;
89 info->parent = parent;
90 info->parent_type = parent_type;
91 info->substmt = substmt;
92 info->substmt_index = substmt_index;
Radek Krejci2b999ac2017-01-18 16:22:12 +010093 info->ext_index = ext_index;
Radek Krejci07d0fb92017-01-13 14:11:05 +010094
95 if (unres_schema_add_node(module, unres, ext, UNRES_EXT, (struct lys_node *)info) == -1) {
96 return EXIT_FAILURE;
97 }
98
99 return EXIT_SUCCESS;
100}
101
Michal Vasko0d343d12015-08-24 14:57:36 +0200102/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200103static const char *
104read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +0200105{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200106 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200107
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200108 /* there should be <text> child */
109 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
Radek Krejci218436d2016-02-10 12:54:06 +0100110 LOGERR(LY_EVALID, "Expected \"%s\" element in \"%s\" element.", name, node->name);
Radek Krejci48464ed2016-03-17 15:44:09 +0100111 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, node->name);
Radek Krejci218436d2016-02-10 12:54:06 +0100112 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200113 } else if (node->child->content) {
114 len = strlen(node->child->content);
115 return lydict_insert(ctx, node->child->content, len);
Radek Krejci218436d2016-02-10 12:54:06 +0100116 } else {
117 return lydict_insert(ctx, "", 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200118 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200119}
120
Radek Krejcie534c132016-11-23 13:32:31 +0100121static int
Radek Krejci07d0fb92017-01-13 14:11:05 +0100122read_yin_subnode_ext(struct lys_module *mod, void *elem, LYEXT_PAR elem_type,
Radek Krejciac00b2a2017-01-17 14:05:00 +0100123 struct lyxml_elem *yin, LYEXT_SUBSTMT type, uint8_t i, struct unres_schema *unres)
Radek Krejcie534c132016-11-23 13:32:31 +0100124{
Radek Krejci07d0fb92017-01-13 14:11:05 +0100125 void *reallocated;
126 struct lyxml_elem *next, *child;
127 int r;
128 struct lys_ext_instance ***ext;
129 uint8_t *ext_size;
Radek Krejcie534c132016-11-23 13:32:31 +0100130
Radek Krejci07d0fb92017-01-13 14:11:05 +0100131 switch (elem_type) {
132 case LYEXT_PAR_MODULE:
133 ext_size = &((struct lys_module *)elem)->ext_size;
134 ext = &((struct lys_module *)elem)->ext;
135 break;
136 case LYEXT_PAR_NODE:
137 ext_size = &((struct lys_node *)elem)->ext_size;
138 ext = &((struct lys_node *)elem)->ext;
139 break;
140 case LYEXT_PAR_IDENT:
141 ext_size = &((struct lys_ident *)elem)->ext_size;
142 ext = &((struct lys_ident *)elem)->ext;
143 break;
144 case LYEXT_PAR_TYPE_BIT:
145 ext_size = &((struct lys_type_bit *)elem)->ext_size;
146 ext = &((struct lys_type_bit *)elem)->ext;
147 break;
148 case LYEXT_PAR_TYPE_ENUM:
149 ext_size = &((struct lys_type_enum *)elem)->ext_size;
150 ext = &((struct lys_type_enum *)elem)->ext;
151 break;
152 case LYEXT_PAR_TPDF:
153 ext_size = &((struct lys_tpdf *)elem)->ext_size;
154 ext = &((struct lys_tpdf *)elem)->ext;
155 break;
156 case LYEXT_PAR_EXT:
157 ext_size = &((struct lys_ext *)elem)->ext_size;
158 ext = &((struct lys_ext *)elem)->ext;
159 break;
160 case LYEXT_PAR_FEATURE:
161 ext_size = &((struct lys_feature *)elem)->ext_size;
162 ext = &((struct lys_feature *)elem)->ext;
163 break;
164 case LYEXT_PAR_REFINE:
165 ext_size = &((struct lys_refine *)elem)->ext_size;
166 ext = &((struct lys_refine *)elem)->ext;
167 break;
Radek Krejcifccd1442017-01-16 10:26:57 +0100168 case LYEXT_PAR_MUST:
169 case LYEXT_PAR_PATTERN:
170 case LYEXT_PAR_LENGTH:
171 case LYEXT_PAR_RANGE:
172 ext_size = &((struct lys_restr *)elem)->ext_size;
173 ext = &((struct lys_restr *)elem)->ext;
174 break;
Radek Krejci5323b492017-01-16 15:40:11 +0100175 case LYEXT_PAR_WHEN:
176 ext_size = &((struct lys_when *)elem)->ext_size;
177 ext = &((struct lys_when *)elem)->ext;
178 break;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100179 default:
Radek Krejcifccd1442017-01-16 10:26:57 +0100180 LOGERR(LY_EINT, "parent type %d", elem_type);
Radek Krejcie534c132016-11-23 13:32:31 +0100181 return EXIT_FAILURE;
182 }
183
Radek Krejcifccd1442017-01-16 10:26:57 +0100184 if (type == LYEXT_SUBSTMT_SELF) {
185 /* parse for the statement self, not for the substatement */
186 child = yin;
187 next = NULL;
188 goto parseext;
189 }
190
Radek Krejci07d0fb92017-01-13 14:11:05 +0100191 LY_TREE_FOR_SAFE(yin->child, next, child) {
192 if (!strcmp(child->ns->value, LY_NSYIN)) {
193 /* skip the regular YIN nodes */
194 continue;
195 }
196
197 /* parse it as extension */
Radek Krejcifccd1442017-01-16 10:26:57 +0100198parseext:
Radek Krejci07d0fb92017-01-13 14:11:05 +0100199
200 /* first, allocate a space for the extension instance in the parent elem */
201 reallocated = realloc(*ext, (1 + (*ext_size)) * sizeof **ext);
202 if (!reallocated) {
203 LOGMEM;
204 return EXIT_FAILURE;
205 }
206 (*ext) = reallocated;
207
208 /* init memory */
209 (*ext)[(*ext_size)] = NULL;
210
211 /* parse YIN data */
Radek Krejci2b999ac2017-01-18 16:22:12 +0100212 r = lyp_yin_fill_ext(elem, elem_type, type, i, mod, child, &(*ext), (*ext_size), unres);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100213 (*ext_size)++;
214 if (r) {
215 return EXIT_FAILURE;
216 }
217
Radek Krejcifccd1442017-01-16 10:26:57 +0100218 /* done - do not free the child, it is unlinked in lyp_yin_fill_ext */
Radek Krejci07d0fb92017-01-13 14:11:05 +0100219 }
220
Radek Krejcie534c132016-11-23 13:32:31 +0100221 return EXIT_SUCCESS;
222}
223
Michal Vasko0d343d12015-08-24 14:57:36 +0200224/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200225static int
Radek Krejci9de2c042016-10-19 16:53:06 +0200226fill_yin_iffeature(struct lys_node *parent, int parent_is_feature, struct lyxml_elem *yin, struct lys_iffeature *iffeat,
227 struct unres_schema *unres)
Michal Vasko1d337e12016-02-15 12:32:04 +0100228{
Radek Krejci5323b492017-01-16 15:40:11 +0100229 int r, c_ext = 0;
Michal Vasko1d337e12016-02-15 12:32:04 +0100230 const char *value;
Radek Krejci5323b492017-01-16 15:40:11 +0100231 struct lyxml_elem *node, *next;
Michal Vasko1d337e12016-02-15 12:32:04 +0100232
233 GETVAL(value, yin, "name");
Michal Vasko97b32be2016-07-25 10:59:53 +0200234
235 if ((lys_node_module(parent)->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
236 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
Radek Krejci9ff0a922016-07-14 13:08:05 +0200237error:
Michal Vasko1d337e12016-02-15 12:32:04 +0100238 return EXIT_FAILURE;
239 }
240
Michal Vasko56d082c2016-10-25 14:00:42 +0200241 if (!(value = transform_iffeat_schema2json(parent->module, value))) {
Michal Vasko1d337e12016-02-15 12:32:04 +0100242 return EXIT_FAILURE;
243 }
244
Radek Krejci9de2c042016-10-19 16:53:06 +0200245 r = resolve_iffeature_compile(iffeat, value, parent, parent_is_feature, unres);
Michal Vasko1d337e12016-02-15 12:32:04 +0100246 lydict_remove(parent->module->ctx, value);
Radek Krejci9ff0a922016-07-14 13:08:05 +0200247 if (r) {
248 return EXIT_FAILURE;
Michal Vasko1d337e12016-02-15 12:32:04 +0100249 }
250
Radek Krejci5323b492017-01-16 15:40:11 +0100251 LY_TREE_FOR_SAFE(yin->child, next, node) {
252 if (!node->ns) {
253 /* garbage */
254 lyxml_free(parent->module->ctx, node);
255 } else if (strcmp(node->ns->value, LY_NSYIN)) {
256 /* extension */
257 c_ext++;
258 } else {
259 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "if-feature");
260 return EXIT_FAILURE;
261 }
262 }
263 if (c_ext) {
264 iffeat->ext = calloc(c_ext, sizeof *iffeat->ext);
265 if (!iffeat->ext) {
266 LOGMEM;
267 return EXIT_FAILURE;
268 }
269 LY_TREE_FOR_SAFE(yin->child, next, node) {
270 /* extensions */
271 r = lyp_yin_fill_ext(iffeat, LYEXT_PAR_IDENT, 0, 0, parent->module, node,
Radek Krejci2b999ac2017-01-18 16:22:12 +0100272 &iffeat->ext, iffeat->ext_size, unres);
Radek Krejci5323b492017-01-16 15:40:11 +0100273 iffeat->ext_size++;
274 if (r) {
275 return EXIT_FAILURE;
276 }
277 }
278 }
279
Radek Krejci9ff0a922016-07-14 13:08:05 +0200280 return EXIT_SUCCESS;
Michal Vasko1d337e12016-02-15 12:32:04 +0100281}
282
283/* logs directly */
284static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200285fill_yin_identity(struct lys_module *module, struct lyxml_elem *yin, struct lys_ident *ident, struct unres_schema *unres)
Radek Krejci04581c62015-05-22 21:24:00 +0200286{
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200287 struct lyxml_elem *node, *next;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200288 const char *value;
Radek Krejci018f1f52016-08-03 16:01:20 +0200289 int rc;
Radek Krejcie534c132016-11-23 13:32:31 +0100290 int c_ftrs = 0, c_base = 0, c_ext = 0;
Radek Krejci04581c62015-05-22 21:24:00 +0200291
Michal Vasko4cfcd252015-08-03 14:31:10 +0200292 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100293 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200294
Radek Krejci07d0fb92017-01-13 14:11:05 +0100295 if (read_yin_common(module, NULL, ident, LYEXT_PAR_IDENT, yin, OPT_IDENT | OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200296 return EXIT_FAILURE;
297 }
Radek Krejci04581c62015-05-22 21:24:00 +0200298
Pavol Vicand6cda452016-07-13 15:08:29 +0200299 if (dup_identities_check(ident->name, module)) {
300 return EXIT_FAILURE;
301 }
302
Radek Krejcie534c132016-11-23 13:32:31 +0100303 LY_TREE_FOR(yin->child, node) {
304 if (strcmp(node->ns->value, LY_NSYIN)) {
305 /* extension */
306 c_ext++;
307 } else if (!strcmp(node->name, "base")) {
Radek Krejci018f1f52016-08-03 16:01:20 +0200308 if (c_base && (module->version < 2)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100309 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200310 return EXIT_FAILURE;
311 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200312 c_base++;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100313
Radek Krejci018f1f52016-08-03 16:01:20 +0200314 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
315 c_ftrs++;
316
317 } else {
318 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
319 return EXIT_FAILURE;
320 }
321 }
322
323 if (c_base) {
324 ident->base_size = 0;
325 ident->base = calloc(c_base, sizeof *ident->base);
326 if (!ident->base) {
327 LOGMEM;
328 return EXIT_FAILURE;
329 }
330 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200331 if (c_ftrs) {
332 ident->iffeature = calloc(c_ftrs, sizeof *ident->iffeature);
333 if (!ident->iffeature) {
334 LOGMEM;
335 return EXIT_FAILURE;
336 }
337 }
Radek Krejcie534c132016-11-23 13:32:31 +0100338 if (c_ext) {
339 ident->ext = calloc(c_ext, sizeof *ident->ext);
340 if (!ident->ext) {
341 LOGMEM;
342 return EXIT_FAILURE;
343 }
344 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200345
Radek Krejcie534c132016-11-23 13:32:31 +0100346 LY_TREE_FOR_SAFE(yin->child, next, node) {
347 if (strcmp(node->ns->value, LY_NSYIN)) {
348 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +0100349 rc = lyp_yin_fill_ext(ident, LYEXT_PAR_IDENT, 0, 0, module, node, &ident->ext, ident->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +0100350 ident->ext_size++;
351 if (rc) {
352 goto error;
353 }
354 } else if (!strcmp(node->name, "base")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200355 GETVAL(value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100356 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100357 if (!value) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200358 return EXIT_FAILURE;
359 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100360
Radek Krejci48464ed2016-03-17 15:44:09 +0100361 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vaskoc94283a2015-10-29 09:07:20 +0100362 lydict_remove(module->ctx, value);
363 return EXIT_FAILURE;
364 }
365 lydict_remove(module->ctx, value);
Radek Krejci018f1f52016-08-03 16:01:20 +0200366 } else if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200367 rc = fill_yin_iffeature((struct lys_node *)ident, 0, node, &ident->iffeature[ident->iffeature_size], unres);
Radek Krejci018f1f52016-08-03 16:01:20 +0200368 ident->iffeature_size++;
369 if (rc) {
370 return EXIT_FAILURE;
371 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200372 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200373 }
Radek Krejci04581c62015-05-22 21:24:00 +0200374
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200375 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200376
377error:
378 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200379}
380
Michal Vasko0d343d12015-08-24 14:57:36 +0200381/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200382static int
Radek Krejcifccd1442017-01-16 10:26:57 +0100383read_restr_substmt(struct lys_module *module, LYEXT_PAR restr_type, struct lys_restr *restr, struct lyxml_elem *yin,
384 struct unres_schema *unres)
Radek Krejci41726f92015-06-19 13:11:05 +0200385{
Radek Krejcifccd1442017-01-16 10:26:57 +0100386 struct lyxml_elem *child, *next;
Radek Krejci461d1622015-06-30 14:06:28 +0200387 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200388
Radek Krejcifccd1442017-01-16 10:26:57 +0100389 LY_TREE_FOR_SAFE(yin->child, next, child) {
390 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200391 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200392 continue;
Radek Krejcifccd1442017-01-16 10:26:57 +0100393 } else if (strcmp(child->ns->value, LY_NSYIN)) {
394 /* extension */
Radek Krejciac00b2a2017-01-17 14:05:00 +0100395 if (read_yin_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100396 return EXIT_FAILURE;
397 }
398 } else if (!strcmp(child->name, "description")) {
Radek Krejci41726f92015-06-19 13:11:05 +0200399 if (restr->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100400 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200401 return EXIT_FAILURE;
402 }
Radek Krejciac00b2a2017-01-17 14:05:00 +0100403 if (read_yin_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100404 return EXIT_FAILURE;
405 }
406 restr->dsc = read_yin_subnode(module->ctx, child, "text");
Radek Krejci41726f92015-06-19 13:11:05 +0200407 if (!restr->dsc) {
408 return EXIT_FAILURE;
409 }
410 } else if (!strcmp(child->name, "reference")) {
411 if (restr->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100412 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200413 return EXIT_FAILURE;
414 }
Radek Krejciac00b2a2017-01-17 14:05:00 +0100415 if (read_yin_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100416 return EXIT_FAILURE;
417 }
418 restr->ref = read_yin_subnode(module->ctx, child, "text");
Radek Krejci41726f92015-06-19 13:11:05 +0200419 if (!restr->ref) {
420 return EXIT_FAILURE;
421 }
422 } else if (!strcmp(child->name, "error-app-tag")) {
423 if (restr->eapptag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100424 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200425 return EXIT_FAILURE;
426 }
Radek Krejciac00b2a2017-01-17 14:05:00 +0100427 if (read_yin_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_ERRTAG, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100428 return EXIT_FAILURE;
429 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200430 GETVAL(value, child, "value");
Radek Krejcifccd1442017-01-16 10:26:57 +0100431 restr->eapptag = lydict_insert(module->ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200432 } else if (!strcmp(child->name, "error-message")) {
433 if (restr->emsg) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100434 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200435 return EXIT_FAILURE;
436 }
Radek Krejciac00b2a2017-01-17 14:05:00 +0100437 if (read_yin_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_ERRMSG, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100438 return EXIT_FAILURE;
439 }
440 restr->emsg = read_yin_subnode(module->ctx, child, "value");
Radek Krejci41726f92015-06-19 13:11:05 +0200441 if (!restr->emsg) {
442 return EXIT_FAILURE;
443 }
444 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100445 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200446 return EXIT_FAILURE;
447 }
Radek Krejci41726f92015-06-19 13:11:05 +0200448 }
449
450 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200451
452error:
453 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200454}
455
Michal Vasko88c29542015-11-27 14:57:53 +0100456/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
457int
Radek Krejcib8048692015-08-05 13:36:34 +0200458fill_yin_type(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_type *type,
Radek Krejci3a5501d2016-07-18 22:03:34 +0200459 int tpdftype, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200460{
Michal Vasko0aee5c12016-06-17 14:27:26 +0200461 const char *value, *name;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200462 struct lys_node *siter;
Radek Krejcie534c132016-11-23 13:32:31 +0100463 struct lyxml_elem *next, *next2, *node, *child, exts;
Radek Krejcifccd1442017-01-16 10:26:57 +0100464 struct lys_restr **restrs, *restr;
Radek Krejci1c5890d2016-08-02 13:15:42 +0200465 struct lys_type_bit bit, *bits_sc = NULL;
466 struct lys_type_enum *enms_sc = NULL; /* shortcut */
Radek Krejcie663e012016-08-01 17:12:34 +0200467 struct lys_type *dertype;
Radek Krejcie534c132016-11-23 13:32:31 +0100468 int i, j, rc, val_set, c_ftrs, c_ext = 0;
Radek Krejcidc008d72016-02-17 13:12:14 +0100469 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200470 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200471 int64_t p, p_;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200472 size_t len;
473 char *buf, modifier;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200474
Radek Krejcie534c132016-11-23 13:32:31 +0100475 /* init */
476 memset(&exts, 0, sizeof exts);
477
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200478 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100479 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200480 if (!value) {
481 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200482 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200483
484 i = parse_identifier(value);
485 if (i < 1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100486 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100487 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200488 goto error;
489 }
490 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100491 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200492 if (value[i]) {
493 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100494 name += i;
495 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100496 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100497 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200498 goto error;
499 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200500 /* name is in dictionary, but moved */
Radek Krejci225376f2016-02-16 17:36:22 +0100501 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200502 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200503
Radek Krejci225376f2016-02-16 17:36:22 +0100504 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200505 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100506 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200507 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200508 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100509
510 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200511 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200512 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200513 lydict_remove(module->ctx, value);
Radek Krejcidc008d72016-02-17 13:12:14 +0100514 ret = EXIT_FAILURE;
515 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200516 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200517 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200518
Radek Krejci9b6aad22016-09-20 15:55:51 +0200519 if (type->base == LY_TYPE_ERR) {
Radek Krejcic13db382016-08-16 10:52:42 +0200520 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Radek Krejci9b6aad22016-09-20 15:55:51 +0200521 * unresolved item left inside the grouping, LY_TYPE_ERR used as a flag for types inside a grouping. */
Radek Krejcic13db382016-08-16 10:52:42 +0200522 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
523 if (siter) {
Radek Krejci6ff885d2017-01-03 14:06:22 +0100524#if __BYTE_ORDER == __LITTLE_ENDIAN
525 if (!((uint8_t*)&((struct lys_node_grp *)siter)->flags)[1]) {
Radek Krejcic13db382016-08-16 10:52:42 +0200526 LOGINT;
527 goto error;
528 }
Radek Krejci6ff885d2017-01-03 14:06:22 +0100529 ((uint8_t*)&((struct lys_node_grp *)siter)->flags)[1]--;
530#else
531 if (!((uint8_t*)&((struct lys_node_grp *)siter)->flags)[0]) {
532 LOGINT;
533 goto error;
534 }
535 ((uint8_t*)&((struct lys_node_grp *)siter)->flags)[0]--;
536#endif
Radek Krejcic13db382016-08-16 10:52:42 +0200537 } else {
538 LOGINT;
539 goto error;
540 }
541 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200542 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200543
Radek Krejcicf509982015-12-15 09:22:44 +0100544 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100545 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejci48464ed2016-03-17 15:44:09 +0100546 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100547 return -1;
548 }
549
Radek Krejcie534c132016-11-23 13:32:31 +0100550 /* parse extension instances */
551 LY_TREE_FOR_SAFE(yin->child, next, node) {
552 if (!node->ns) {
553 /* garbage */
554 lyxml_free(module->ctx, node);
555 continue;
556 } else if (!strcmp(node->ns->value, LY_NSYIN)) {
557 /* YANG (YIN) statements - process later */
558 continue;
559 }
560
561 lyxml_unlink_elem(module->ctx, node, 2);
562 lyxml_add_child(module->ctx, &exts, node);
563 c_ext++;
564 }
565 if (c_ext) {
566 type->ext = calloc(c_ext, sizeof *type->ext);
567 if (!type->ext) {
568 LOGMEM;
569 goto error;
570 }
571 LY_TREE_FOR_SAFE(exts.child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +0100572 rc = lyp_yin_fill_ext(type, LYEXT_PAR_TYPE, 0, 0, module, node, &type->ext, type->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +0100573 type->ext_size++;
574 if (rc) {
575 goto error;
576 }
577 }
578 }
579
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200580 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200581 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200582 /* RFC 6020 9.7.4 - bit */
583
584 /* get bit specifications, at least one must be present */
585 LY_TREE_FOR_SAFE(yin->child, next, node) {
586 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200587 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200588 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100589 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200590 type->info.bits.count = 0;
Radek Krejci41726f92015-06-19 13:11:05 +0200591 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200592 }
593 }
Radek Krejcie663e012016-08-01 17:12:34 +0200594 dertype = &type->der->type;
595 if (!dertype->der) {
596 if (!type->info.bits.count) {
597 /* type is derived directly from buit-in bits type and bit statement is required */
598 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
599 goto error;
600 }
601 } else {
602 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
603 if (module->version < 2 && type->info.bits.count) {
604 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
605 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
606 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejci69794c62016-08-02 11:01:21 +0200607 type->info.bits.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200608 goto error;
609 }
Radek Krejciac781922015-07-09 15:35:14 +0200610 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200611
612 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100613 if (!type->info.bits.bit) {
614 LOGMEM;
615 goto error;
616 }
Radek Krejci73adb602015-07-02 18:07:40 +0200617 p = 0;
618 i = -1;
619 LY_TREE_FOR(yin->child, next) {
620 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200621 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200622
623 GETVAL(value, next, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100624 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100625 goto error;
626 }
627
Radek Krejci994b6f62015-06-18 16:47:27 +0200628 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100629 if (read_yin_common(module, NULL, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, next, 0, unres)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200630 type->info.bits.count = i + 1;
631 goto error;
632 }
633
Radek Krejcie663e012016-08-01 17:12:34 +0200634 if (!dertype->der) { /* directly derived type from bits built-in type */
635 /* check the name uniqueness */
636 for (j = 0; j < i; j++) {
637 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
638 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
639 type->info.bits.count = i + 1;
640 goto error;
641 }
642 }
643 } else {
644 /* restricted bits type - the name MUST be used in the base type */
645 bits_sc = dertype->info.bits.bit;
646 for (j = 0; j < dertype->info.bits.count; j++) {
647 if (ly_strequal(bits_sc[j].name, value, 1)) {
648 break;
649 }
650 }
651 if (j == dertype->info.bits.count) {
652 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci994b6f62015-06-18 16:47:27 +0200653 type->info.bits.count = i + 1;
654 goto error;
655 }
656 }
657
Radek Krejcie663e012016-08-01 17:12:34 +0200658
Radek Krejci0d70c372015-07-02 16:23:10 +0200659 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200660 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200661 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
662 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200663 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200664 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200665
Radek Krejci0d70c372015-07-02 16:23:10 +0200666 if (!strcmp(node->name, "position")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200667 if (p_ != -1) {
668 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
669 type->info.bits.count = i + 1;
670 goto error;
671 }
672
Radek Krejci0d70c372015-07-02 16:23:10 +0200673 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200674 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200675
676 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200677 if (p_ < 0 || p_ > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100678 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200679 type->info.bits.count = i + 1;
680 goto error;
681 }
682 type->info.bits.bit[i].pos = (uint32_t)p_;
683
Radek Krejcie663e012016-08-01 17:12:34 +0200684 if (!dertype->der) { /* directly derived type from bits built-in type */
685 /* keep the highest enum value for automatic increment */
686 if (type->info.bits.bit[i].pos >= p) {
687 p = type->info.bits.bit[i].pos;
688 p++;
689 } else {
690 /* check that the value is unique */
691 for (j = 0; j < i; j++) {
692 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
693 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
694 type->info.bits.bit[i].pos, type->info.bits.bit[i].name,
695 type->info.bits.bit[j].name);
696 type->info.bits.count = i + 1;
697 goto error;
698 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200699 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200700 }
701 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200702
703 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
704 c_ftrs++;
Radek Krejci0d70c372015-07-02 16:23:10 +0200705 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100706 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200707 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200708 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200709 }
Radek Krejcie663e012016-08-01 17:12:34 +0200710
711 if (!dertype->der) { /* directly derived type from bits built-in type */
712 if (p_ == -1) {
713 /* assign value automatically */
714 if (p > UINT32_MAX) {
715 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
716 type->info.bits.count = i + 1;
717 goto error;
718 }
719 type->info.bits.bit[i].pos = (uint32_t)p;
720 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
721 p++;
Radek Krejci994b6f62015-06-18 16:47:27 +0200722 }
Radek Krejcie663e012016-08-01 17:12:34 +0200723 } else { /* restricted bits type */
724 if (p_ == -1) {
725 /* automatically assign position from base type */
726 type->info.bits.bit[i].pos = bits_sc[j].pos;
727 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
728 } else {
729 /* check that the assigned position corresponds to the original
730 * position of the bit in the base type */
731 if (p_ != bits_sc[j].pos) {
732 /* p_ - assigned position in restricted bits
733 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
734 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
Radek Krejci541a45d2016-08-02 13:12:07 +0200735 type->info.bits.bit[i].name, bits_sc[j].pos);
Radek Krejcie663e012016-08-01 17:12:34 +0200736 type->info.bits.count = i + 1;
737 goto error;
738 }
739 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200740 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200741
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200742 /* if-features */
743 if (c_ftrs) {
744 bits_sc = &type->info.bits.bit[i];
745 bits_sc->iffeature = calloc(c_ftrs, sizeof *bits_sc->iffeature);
746 if (!bits_sc->iffeature) {
747 LOGMEM;
Radek Krejci994b6f62015-06-18 16:47:27 +0200748 type->info.bits.count = i + 1;
749 goto error;
750 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200751
752 LY_TREE_FOR(next->child, node) {
753 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200754 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200755 &bits_sc->iffeature[bits_sc->iffeature_size], unres);
756 bits_sc->iffeature_size++;
757 if (rc) {
758 type->info.bits.count = i + 1;
759 goto error;
760 }
761 }
762 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200763 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200764
765 /* keep them ordered by position */
766 j = i;
767 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
768 /* switch them */
769 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
770 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
771 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
772 j--;
773 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200774 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200775 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200776
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200777 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200778 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200779 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200780
Radek Krejcif9401c32015-06-26 16:47:36 +0200781 if (!strcmp(node->name, "range")) {
782 if (type->info.dec64.range) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100783 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200784 goto error;
785 }
786
787 GETVAL(value, node, "value");
Radek Krejcif9401c32015-06-26 16:47:36 +0200788 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100789 if (!type->info.dec64.range) {
790 LOGMEM;
791 goto error;
792 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200793 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
794
795 /* get possible substatements */
Radek Krejcifccd1442017-01-16 10:26:57 +0100796 if (read_restr_substmt(module, LYEXT_PAR_RANGE, type->info.dec64.range, node, unres)) {
Radek Krejcif9401c32015-06-26 16:47:36 +0200797 goto error;
798 }
799 } else if (!strcmp(node->name, "fraction-digits")) {
800 if (type->info.dec64.dig) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100801 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200802 goto error;
803 }
804 GETVAL(value, node, "value");
805 v = strtol(value, NULL, 10);
806
807 /* range check */
808 if (v < 1 || v > 18) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100809 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200810 goto error;
811 }
812 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200813 type->info.dec64.div = 10;
814 for (i = 1; i < v; i++) {
815 type->info.dec64.div *= 10;
816 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200817 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100818 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200819 goto error;
820 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200821 }
822
823 /* mandatory sub-statement(s) check */
824 if (!type->info.dec64.dig && !type->der->type.der) {
825 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejci48464ed2016-03-17 15:44:09 +0100826 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200827 goto error;
828 }
Radek Krejci7511f402015-07-10 09:56:30 +0200829 if (type->info.dec64.dig && type->der->type.der) {
830 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100831 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200832 goto error;
833 }
Radek Krejci4800f652016-09-08 14:02:52 +0200834
835 /* copy fraction-digits specification from parent type for easier internal use */
836 if (type->der->type.der) {
837 type->info.dec64.dig = type->der->type.info.dec64.dig;
838 type->info.dec64.div = type->der->type.info.dec64.div;
839 }
840
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200841 if (type->info.dec64.range && lyp_check_length_range(type->info.dec64.range->expr, type)) {
842 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
843 goto error;
844 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200845 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200846
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200847 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200848 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200849
Radek Krejci994b6f62015-06-18 16:47:27 +0200850 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200851 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200852
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200853 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200854 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200855 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100856 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200857 type->info.enums.count = 0;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200858 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200859 }
860 }
Radek Krejcie663e012016-08-01 17:12:34 +0200861 dertype = &type->der->type;
862 if (!dertype->der) {
863 if (!type->info.enums.count) {
864 /* type is derived directly from buit-in enumeartion type and enum statement is required */
865 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
866 goto error;
867 }
868 } else {
869 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
870 if (module->version < 2 && type->info.enums.count) {
871 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
872 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
873 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejci69794c62016-08-02 11:01:21 +0200874 type->info.enums.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200875 goto error;
876 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200877 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200878
Radek Krejci1574a8d2015-08-03 14:16:52 +0200879 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100880 if (!type->info.enums.enm) {
881 LOGMEM;
882 goto error;
883 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200884
Radek Krejcie663e012016-08-01 17:12:34 +0200885 v = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200886 i = -1;
887 LY_TREE_FOR(yin->child, next) {
888 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200889 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200890
891 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100892 if (!value[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100893 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
894 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100895 goto error;
896 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200897 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100898 if (read_yin_common(module, NULL, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, next, 0, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200899 type->info.enums.count = i + 1;
900 goto error;
901 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200902
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200903 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200904 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200905 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100906 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200907 type->info.enums.count = i + 1;
908 goto error;
909 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200910
Radek Krejcie663e012016-08-01 17:12:34 +0200911 if (!dertype->der) { /* directly derived type from enumeration built-in type */
912 /* check the name uniqueness */
913 for (j = 0; j < i; j++) {
914 if (ly_strequal(type->info.enums.enm[j].name, value, 1)) {
915 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, value);
916 type->info.enums.count = i + 1;
917 goto error;
918 }
919 }
920 } else {
921 /* restricted enumeration type - the name MUST be used in the base type */
922 enms_sc = dertype->info.enums.enm;
923 for (j = 0; j < dertype->info.enums.count; j++) {
924 if (ly_strequal(enms_sc[j].name, value, 1)) {
925 break;
926 }
927 }
928 if (j == dertype->info.enums.count) {
929 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200930 type->info.enums.count = i + 1;
931 goto error;
932 }
933 }
Radek Krejci04581c62015-05-22 21:24:00 +0200934
Radek Krejcie663e012016-08-01 17:12:34 +0200935 val_set = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200936 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200937 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
938 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200939 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200940 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200941
Radek Krejci0d70c372015-07-02 16:23:10 +0200942 if (!strcmp(node->name, "value")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200943 if (val_set) {
944 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
945 type->info.enums.count = i + 1;
946 goto error;
947 }
948
Radek Krejci0d70c372015-07-02 16:23:10 +0200949 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200950 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200951
952 /* range check */
953 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100954 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200955 type->info.enums.count = i + 1;
956 goto error;
957 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200958 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200959
Radek Krejcie663e012016-08-01 17:12:34 +0200960 if (!dertype->der) { /* directly derived type from enumeration built-in type */
Pavol Vican5de389c2016-08-30 08:55:15 +0200961 if (!i) {
962 /* change value, which is assigned automatically, if first enum has value. */
Radek Krejcie663e012016-08-01 17:12:34 +0200963 v = type->info.enums.enm[i].value;
964 v++;
965 } else {
Pavol Vican5de389c2016-08-30 08:55:15 +0200966 /* keep the highest enum value for automatic increment */
967 if (type->info.enums.enm[i].value >= v) {
968 v = type->info.enums.enm[i].value;
969 v++;
970 } else {
971 /* check that the value is unique */
972 for (j = 0; j < i; j++) {
973 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
974 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
975 type->info.enums.enm[i].value, type->info.enums.enm[i].name,
976 type->info.enums.enm[j].name);
977 type->info.enums.count = i + 1;
978 goto error;
979 }
Radek Krejcie663e012016-08-01 17:12:34 +0200980 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200981 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200982 }
983 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200984 val_set = 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200985
986 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
987 c_ftrs++;
988
Radek Krejci0d70c372015-07-02 16:23:10 +0200989 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100990 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200991 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200992 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200993 }
Radek Krejcie663e012016-08-01 17:12:34 +0200994
995 if (!dertype->der) { /* directly derived type from enumeration */
996 if (!val_set) {
997 /* assign value automatically */
998 if (v > INT32_MAX) {
999 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
1000 type->info.enums.count = i + 1;
1001 goto error;
1002 }
1003 type->info.enums.enm[i].value = v;
1004 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1005 v++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001006 }
Radek Krejcie663e012016-08-01 17:12:34 +02001007 } else { /* restricted enum type */
1008 if (!val_set) {
1009 /* automatically assign value from base type */
1010 type->info.enums.enm[i].value = enms_sc[j].value;
1011 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1012 } else {
1013 /* check that the assigned value corresponds to the original
1014 * value of the enum in the base type */
1015 if (v_ != enms_sc[j].value) {
1016 /* v_ - assigned value in restricted enum
1017 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
1018 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL,
Radek Krejci541a45d2016-08-02 13:12:07 +02001019 type->info.enums.enm[i].value, type->info.enums.enm[i].name, enms_sc[j].value);
Radek Krejcie663e012016-08-01 17:12:34 +02001020 type->info.enums.count = i + 1;
1021 goto error;
1022 }
1023 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001024 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001025
1026 /* if-features */
1027 if (c_ftrs) {
1028 enms_sc = &type->info.enums.enm[i];
1029 enms_sc->iffeature = calloc(c_ftrs, sizeof *enms_sc->iffeature);
1030 if (!enms_sc->iffeature) {
1031 LOGMEM;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001032 type->info.enums.count = i + 1;
1033 goto error;
1034 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001035
1036 LY_TREE_FOR(next->child, node) {
1037 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02001038 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001039 &enms_sc->iffeature[enms_sc->iffeature_size], unres);
1040 enms_sc->iffeature_size++;
1041 if (rc) {
1042 type->info.enums.count = i + 1;
1043 goto error;
1044 }
1045 }
1046 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001047 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001048
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001049 }
1050 break;
1051
1052 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +02001053 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001054
Michal Vaskof2d43962016-09-02 11:10:16 +02001055 /* get base specification, at least one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +02001056 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001057
Michal Vaskoe29c6622015-11-27 15:02:31 +01001058 if (strcmp(node->name, "base")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001059 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001060 goto error;
1061 }
Michal Vaskof2d43962016-09-02 11:10:16 +02001062
1063 GETVAL(value, yin->child, "name");
1064 /* store in the JSON format */
1065 value = transform_schema2json(module, value);
1066 if (!value) {
1067 goto error;
1068 }
1069 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
1070 lydict_remove(module->ctx, value);
1071
1072 if (rc == -1) {
1073 goto error;
1074 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001075 }
1076
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001077 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +02001078 if (type->der->type.der) {
Michal Vaskof2d43962016-09-02 11:10:16 +02001079 /* this is just a derived type with no base required */
Radek Krejci65c889c2015-06-22 10:17:22 +02001080 break;
1081 }
Radek Krejci48464ed2016-03-17 15:44:09 +01001082 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001083 goto error;
Pavol Vicanf0046f42016-09-07 15:11:09 +02001084 } else {
1085 if (type->der->type.der) {
1086 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
1087 goto error;
1088 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001089 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001090 if (yin->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001091 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001092 goto error;
1093 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001094 break;
1095
1096 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +02001097 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +02001098 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001099
Radek Krejciaf351422015-06-19 14:49:38 +02001100 if (!strcmp(node->name, "require-instance")) {
1101 if (type->info.inst.req) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001102 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001103 goto error;
1104 }
1105 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001106 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001107 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001108 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001109 type->info.inst.req = -1;
1110 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001111 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001112 goto error;
1113 }
1114 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001115 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001116 goto error;
1117 }
Radek Krejciaf351422015-06-19 14:49:38 +02001118 }
Michal Vasko8548cf92015-07-20 15:17:53 +02001119
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001120 break;
1121
Radek Krejcif2860132015-06-20 12:37:20 +02001122 case LY_TYPE_BINARY:
1123 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001124 case LY_TYPE_INT8:
1125 case LY_TYPE_INT16:
1126 case LY_TYPE_INT32:
1127 case LY_TYPE_INT64:
1128 case LY_TYPE_UINT8:
1129 case LY_TYPE_UINT16:
1130 case LY_TYPE_UINT32:
1131 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +02001132 /* RFC 6020 9.2.4 - range */
1133
1134 /* length and range are actually the same restriction, so process
1135 * them by this common code, we just need to differ the name and
1136 * structure where the information will be stored
1137 */
1138 if (type->base == LY_TYPE_BINARY) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001139 restrs = &type->info.binary.length;
Radek Krejcif2860132015-06-20 12:37:20 +02001140 name = "length";
1141 } else {
Radek Krejcifccd1442017-01-16 10:26:57 +01001142 restrs = &type->info.num.range;
Radek Krejcif2860132015-06-20 12:37:20 +02001143 name = "range";
1144 }
1145
Radek Krejci73adb602015-07-02 18:07:40 +02001146 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001147
Radek Krejcif2860132015-06-20 12:37:20 +02001148 if (!strcmp(node->name, name)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001149 if (*restrs) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001150 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001151 goto error;
1152 }
1153
1154 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +02001155 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001156 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +02001157 goto error;
1158 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001159 *restrs = calloc(1, sizeof **restrs);
1160 if (!(*restrs)) {
Michal Vasko253035f2015-12-17 16:58:13 +01001161 LOGMEM;
1162 goto error;
1163 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001164 (*restrs)->expr = lydict_insert(module->ctx, value, 0);
Radek Krejcif2860132015-06-20 12:37:20 +02001165
1166 /* get possible substatements */
Radek Krejcifccd1442017-01-16 10:26:57 +01001167 if (read_restr_substmt(module, type->base == LY_TYPE_BINARY ? LYEXT_PAR_LENGTH : LYEXT_PAR_RANGE,
1168 *restrs, node, unres)) {
Radek Krejcif2860132015-06-20 12:37:20 +02001169 goto error;
1170 }
1171 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001172 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001173 goto error;
1174 }
Radek Krejcif2860132015-06-20 12:37:20 +02001175 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001176 break;
1177
1178 case LY_TYPE_LEAFREF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02001179 /* flag resolving for later use */
1180 if (!tpdftype) {
1181 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
1182 if (siter) {
1183 /* just a flag - do not resolve */
1184 tpdftype = 1;
1185 }
1186 }
1187
Radek Krejcidc4c1412015-06-19 15:39:54 +02001188 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +02001189 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001190
Michal Vasko88c29542015-11-27 14:57:53 +01001191 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +02001192 if (type->info.lref.path) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001193 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001194 goto error;
1195 }
1196
1197 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +02001198 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +01001199 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +02001200 if (!type->info.lref.path) {
1201 goto error;
1202 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001203
1204 /* try to resolve leafref path only when this is instantiated
1205 * leaf, so it is not:
1206 * - typedef's type,
1207 * - in grouping definition,
1208 * - just instantiated in a grouping definition,
1209 * because in those cases the nodes referenced in path might not be present
1210 * and it is not a bug. */
1211 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001212 goto error;
1213 }
Radek Krejcid6353ed2016-09-15 13:30:45 +02001214 } else if (module->version >= 2 && !strcmp(node->name, "require-instance")) {
Michal Vasko08ae53e2016-09-02 12:40:04 +02001215 if (type->info.lref.req) {
1216 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
1217 goto error;
1218 }
1219 GETVAL(value, node, "value");
1220 if (!strcmp(value, "true")) {
1221 type->info.lref.req = 1;
1222 } else if (!strcmp(value, "false")) {
1223 type->info.lref.req = -1;
1224 } else {
1225 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
1226 goto error;
1227 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001228 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001229 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001230 goto error;
1231 }
Radek Krejci73adb602015-07-02 18:07:40 +02001232 }
1233
Radek Krejci742be352016-07-17 12:18:54 +02001234 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001235 if (!type->der->type.der) {
1236 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
1237 goto error;
1238 } else {
1239 /* copy leafref definition into the derived type */
1240 type->info.lref.path = lydict_insert(module->ctx, type->der->type.info.lref.path, 0);
1241 /* and resolve the path at the place we are (if not in grouping/typedef) */
1242 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
1243 goto error;
1244 }
1245
1246 /* add pointer to leafref target, only on leaves (not in typedefs) */
1247 if (type->info.lref.target && lys_leaf_add_leafref_target(type->info.lref.target, (struct lys_node *)type->parent)) {
1248 goto error;
1249 }
1250 }
Radek Krejci742be352016-07-17 12:18:54 +02001251 }
1252
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001253 break;
1254
1255 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +02001256 /* RFC 6020 9.4.4 - length */
1257 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +02001258 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +02001259 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001260
Radek Krejci3733a802015-06-19 13:43:21 +02001261 if (!strcmp(node->name, "length")) {
1262 if (type->info.str.length) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001263 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001264 goto error;
1265 }
1266
1267 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +02001268 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001269 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +02001270 goto error;
1271 }
1272 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +01001273 if (!type->info.str.length) {
1274 LOGMEM;
1275 goto error;
1276 }
Radek Krejci3733a802015-06-19 13:43:21 +02001277 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
1278
Radek Krejci5fbc9162015-06-19 14:11:11 +02001279 /* get possible sub-statements */
Radek Krejcifccd1442017-01-16 10:26:57 +01001280 if (read_restr_substmt(module, LYEXT_PAR_LENGTH, type->info.str.length, node, unres)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001281 goto error;
1282 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001283 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001284 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +02001285 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001286 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001287 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001288 goto error;
1289 }
1290 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001291 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001292 if (i) {
1293 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +01001294 if (!type->info.str.patterns) {
1295 LOGMEM;
1296 goto error;
1297 }
Radek Krejci73adb602015-07-02 18:07:40 +02001298 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +01001299 GETVAL(value, node, "value");
Michal Vasko0aee5c12016-06-17 14:27:26 +02001300 if (lyp_check_pattern(value, NULL)) {
Michal Vasko69068852015-07-13 14:34:31 +02001301 free(type->info.str.patterns);
Radek Krejci9f1e8532016-06-16 11:18:21 +02001302 type->info.str.patterns = NULL;
Michal Vasko69068852015-07-13 14:34:31 +02001303 goto error;
1304 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001305 restr = &type->info.str.patterns[type->info.str.pat_count]; /* shortcut */
Michal Vasko69068852015-07-13 14:34:31 +02001306
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001307 modifier = 0x06; /* ACK */
1308 name = NULL;
Radek Krejcifccd1442017-01-16 10:26:57 +01001309 if (module->version >= 2) {
1310 LY_TREE_FOR_SAFE(node->child, next2, child) {
1311 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
1312 if (name) {
1313 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
1314 goto error;
1315 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001316
Radek Krejcifccd1442017-01-16 10:26:57 +01001317 GETVAL(name, child, "value");
1318 if (!strcmp(name, "invert-match")) {
1319 modifier = 0x15; /* NACK */
1320 } else {
1321 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
1322 goto error;
1323 }
1324 /* get extensions of the modifier */
1325 if (read_yin_subnode_ext(module, restr, LYEXT_PAR_PATTERN, child,
Radek Krejciac00b2a2017-01-17 14:05:00 +01001326 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001327 return EXIT_FAILURE;
1328 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001329
Radek Krejcifccd1442017-01-16 10:26:57 +01001330 lyxml_free(module->ctx, child);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001331 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001332 }
1333 }
1334
1335 len = strlen(value);
1336 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
1337 buf[0] = modifier;
1338 strcpy(&buf[1], value);
1339
Radek Krejcifccd1442017-01-16 10:26:57 +01001340 restr->expr = lydict_insert_zc(module->ctx, buf);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001341
1342 /* get possible sub-statements */
Radek Krejcifccd1442017-01-16 10:26:57 +01001343 if (read_restr_substmt(module, LYEXT_PAR_PATTERN, restr, node, unres)) {
Michal Vasko69068852015-07-13 14:34:31 +02001344 free(type->info.str.patterns);
Pavol Vican9fc5d642016-08-30 15:23:19 +02001345 type->info.str.patterns = NULL;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001346 goto error;
1347 }
Radek Krejci73adb602015-07-02 18:07:40 +02001348 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001349 }
1350 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001351 break;
1352
1353 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001354 /* RFC 6020 7.4 - type */
1355 /* count number of types in union */
1356 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001357 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001358
Radek Krejcie4c366b2015-07-02 10:11:31 +02001359 if (!strcmp(node->name, "type")) {
Radek Krejci038d5d92016-09-12 15:07:15 +02001360 if (type->der->type.der) {
1361 /* type can be a substatement only in "union" type, not in derived types */
1362 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "derived type");
1363 goto error;
1364 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001365 i++;
1366 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001367 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001368 goto error;
1369 }
1370 }
1371
Radek Krejci038d5d92016-09-12 15:07:15 +02001372 if (!i && !type->der->type.der) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001373 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001374 goto error;
1375 }
1376
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001377 /* inherit instid presence information */
1378 if ((type->der->type.base == LY_TYPE_UNION) && type->der->type.info.uni.has_ptr_type) {
1379 type->info.uni.has_ptr_type = 1;
1380 }
1381
Radek Krejcie4c366b2015-07-02 10:11:31 +02001382 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001383 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +01001384 if (!type->info.uni.types) {
1385 LOGMEM;
1386 goto error;
1387 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001388 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001389 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +01001390 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001391 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], tpdftype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +01001392 if (!rc) {
1393 type->info.uni.count++;
1394
Radek Krejci7de36cf2016-09-12 16:18:50 +02001395 if (module->version < 2) {
1396 /* union's type cannot be empty or leafref */
1397 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
1398 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
1399 rc = -1;
1400 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
1401 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
1402 rc = -1;
1403 }
Michal Vasko88c29542015-11-27 14:57:53 +01001404 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001405
1406 if ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_INST)
1407 || (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF)) {
1408 type->info.uni.has_ptr_type = 1;
1409 }
Michal Vasko88c29542015-11-27 14:57:53 +01001410 }
1411 if (rc) {
1412 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
1413 for (i = 0; i < type->info.uni.count; ++i) {
1414 lys_type_free(module->ctx, &type->info.uni.types[i]);
1415 }
1416 free(type->info.uni.types);
1417 type->info.uni.types = NULL;
1418 type->info.uni.count = 0;
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001419 type->info.uni.has_ptr_type = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +02001420 type->der = NULL;
1421 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +01001422
1423 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +01001424 ret = EXIT_FAILURE;
Michal Vasko88c29542015-11-27 14:57:53 +01001425 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001426 goto error;
1427 }
Michal Vasko88c29542015-11-27 14:57:53 +01001428 }
1429 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001430
Michal Vasko88c29542015-11-27 14:57:53 +01001431 case LY_TYPE_BOOL:
1432 case LY_TYPE_EMPTY:
1433 /* no sub-statement allowed */
Radek Krejcie534c132016-11-23 13:32:31 +01001434 if (yin->child) {
1435 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->child->name);
1436 goto error;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001437 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001438 break;
1439
1440 default:
Michal Vasko88c29542015-11-27 14:57:53 +01001441 LOGINT;
1442 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001443 }
1444
1445 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001446
1447error:
Radek Krejcidc008d72016-02-17 13:12:14 +01001448 if (type->module_name) {
1449 lydict_remove(module->ctx, type->module_name);
1450 type->module_name = NULL;
1451 }
Radek Krejcie534c132016-11-23 13:32:31 +01001452 lyxml_free_withsiblings(module->ctx, exts.child);
1453
Radek Krejcidc008d72016-02-17 13:12:14 +01001454 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001455}
1456
Michal Vasko0d343d12015-08-24 14:57:36 +02001457/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001458static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01001459fill_yin_typedef(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_tpdf *tpdf,
1460 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001461{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001462 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +01001463 struct lyxml_elem *node, *next;
Radek Krejcie534c132016-11-23 13:32:31 +01001464 int rc, has_type = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001465
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001466 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001467 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001468 goto error;
1469 }
1470 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001471
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001472 /* generic part - status, description, reference */
Radek Krejci07d0fb92017-01-13 14:11:05 +01001473 if (read_yin_common(module, NULL, tpdf, LYEXT_PAR_TPDF, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001474 goto error;
1475 }
Radek Krejcieac35532015-05-31 19:09:15 +02001476
Michal Vasko88c29542015-11-27 14:57:53 +01001477 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejcie534c132016-11-23 13:32:31 +01001478 if (strcmp(node->ns->value, LY_NSYIN)) {
1479 /* extension */
1480 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02001481 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01001482 } else if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001483 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001484 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001485 goto error;
1486 }
Michal Vasko88c29542015-11-27 14:57:53 +01001487 /* HACK for unres */
1488 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001489 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001490 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001491 goto error;
1492 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001493 has_type = 1;
Radek Krejcie534c132016-11-23 13:32:31 +01001494
Radek Krejci07d0fb92017-01-13 14:11:05 +01001495 /* skip lyxml_free() at the end of the loop, node was freed or at least unlinked in unres processing */
Radek Krejcie534c132016-11-23 13:32:31 +01001496 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001497 } else if (!strcmp(node->name, "default")) {
1498 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001499 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001500 goto error;
1501 }
1502 GETVAL(value, node, "value");
1503 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
1504 } else if (!strcmp(node->name, "units")) {
1505 if (tpdf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001506 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001507 goto error;
1508 }
1509 GETVAL(value, node, "name");
1510 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
1511 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001512 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001513 goto error;
1514 }
Radek Krejcie534c132016-11-23 13:32:31 +01001515
1516 lyxml_free(module->ctx, node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001517 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001518
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001519 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001520 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001521 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001522 goto error;
1523 }
Radek Krejcieac35532015-05-31 19:09:15 +02001524
Michal Vasko478c4652016-07-21 12:55:01 +02001525 /* check default value (if not defined, there still could be some restrictions
1526 * that need to be checked against a default value from a derived type) */
Radek Krejci51673202016-11-01 17:00:32 +01001527 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&tpdf->dflt)) == -1) {
Michal Vasko478c4652016-07-21 12:55:01 +02001528 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001529 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001530
Radek Krejcie534c132016-11-23 13:32:31 +01001531 /* finish extensions parsing */
1532 if (c_ext) {
1533 tpdf->ext = calloc(c_ext, sizeof *tpdf->ext);
1534 if (!tpdf->ext) {
1535 LOGMEM;
1536 goto error;
1537 }
1538 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001539 rc = lyp_yin_fill_ext(tpdf, LYEXT_PAR_TYPE, 0, 0, module, node, &tpdf->ext, tpdf->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01001540 tpdf->ext_size++;
1541 if (rc) {
1542 goto error;
1543 }
1544 }
1545 }
1546
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001547 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001548
1549error:
1550
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001551 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001552}
1553
Radek Krejcia1a6b762016-11-14 09:53:38 +09001554static int
Radek Krejcie534c132016-11-23 13:32:31 +01001555fill_yin_extension(struct lys_module *module, struct lyxml_elem *yin, struct lys_ext *ext, struct unres_schema *unres)
Radek Krejcia1a6b762016-11-14 09:53:38 +09001556{
1557 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01001558 struct lyxml_elem *child, *node, *next, *next2;
1559 int c_ext = 0, rc;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001560
1561 GETVAL(value, yin, "name");
1562
1563 if (lyp_check_identifier(value, LY_IDENT_EXTENSION, module, NULL)) {
1564 goto error;
1565 }
1566 ext->name = lydict_insert(module->ctx, value, strlen(value));
1567
Radek Krejci07d0fb92017-01-13 14:11:05 +01001568 if (read_yin_common(module, NULL, ext, LYEXT_PAR_EXT, yin, OPT_MODULE, unres)) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09001569 goto error;
1570 }
1571
Radek Krejcie534c132016-11-23 13:32:31 +01001572 LY_TREE_FOR_SAFE(yin->child, next, node) {
1573 if (strcmp(node->ns->value, LY_NSYIN)) {
1574 /* possible extension instance */
1575 c_ext++;
1576 } else if (!strcmp(node->name, "argument")) {
1577 /* argument */
1578 GETVAL(value, node, "name");
1579 ext->argument = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcia1a6b762016-11-14 09:53:38 +09001580
Radek Krejcia1a6b762016-11-14 09:53:38 +09001581 /* yin-element */
Radek Krejcie534c132016-11-23 13:32:31 +01001582 LY_TREE_FOR_SAFE(node->child, next2, child) {
1583 if (child->ns == node->ns && !strcmp(child->name, "yin-element")) {
1584 GETVAL(value, child, "value");
1585 if (ly_strequal(value, "true", 0)) {
1586 ext->flags |= LYS_YINELEM;
1587 }
1588 } else if (child->ns) {
1589 /* unexpected YANG statement */
1590 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->name);
1591 goto error;
1592 } /* else garbage, but save resource needed for unlinking */
Radek Krejcia1a6b762016-11-14 09:53:38 +09001593 }
1594
Radek Krejcie534c132016-11-23 13:32:31 +01001595 lyxml_free(module->ctx, node);
1596 } else {
1597 /* unexpected YANG statement */
1598 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->name);
1599 goto error;
1600 }
1601 }
1602
1603 if (c_ext) {
1604 ext->ext = calloc(c_ext, sizeof *ext->ext);
1605 if (!ext->ext) {
1606 LOGMEM;
1607 goto error;
1608 }
1609 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001610 rc = lyp_yin_fill_ext(ext, LYEXT_PAR_EXT, 0, 0, module, node, &ext->ext, ext->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01001611 ext->ext_size++;
1612 if (rc) {
1613 goto error;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001614 }
1615 }
1616 }
1617
Radek Krejci0a498f82017-01-04 16:24:15 +01001618 /* search for plugin */
1619 ext->plugin = ext_get_plugin(ext->name, ext->module->name, ext->module->rev ? ext->module->rev[0].date : NULL);
Radek Krejcia1a6b762016-11-14 09:53:38 +09001620
1621 return EXIT_SUCCESS;
1622
1623error:
1624 return EXIT_FAILURE;
1625}
1626
Michal Vasko0d343d12015-08-24 14:57:36 +02001627/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001628static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001629fill_yin_feature(struct lys_module *module, struct lyxml_elem *yin, struct lys_feature *f, struct unres_schema *unres)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001630{
1631 const char *value;
1632 struct lyxml_elem *child, *next;
Radek Krejcie534c132016-11-23 13:32:31 +01001633 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci5323b492017-01-16 15:40:11 +01001634 void *reallocated;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001635
Radek Krejcib05774c2015-06-18 13:52:59 +02001636 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001637 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001638 goto error;
1639 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001640 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001641 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001642
Radek Krejci07d0fb92017-01-13 14:11:05 +01001643 if (read_yin_common(module, NULL, f, LYEXT_PAR_FEATURE, yin, 0, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001644 goto error;
1645 }
1646
Radek Krejcie534c132016-11-23 13:32:31 +01001647 LY_TREE_FOR(yin->child, child) {
1648 if (strcmp(child->ns->value, LY_NSYIN)) {
1649 /* extension */
1650 c_ext++;
1651 } else if (!strcmp(child->name, "if-feature")) {
1652 c_ftrs++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001653 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001654 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001655 goto error;
1656 }
1657 }
1658
Radek Krejcie534c132016-11-23 13:32:31 +01001659 if (c_ftrs) {
1660 f->iffeature = calloc(c_ftrs, sizeof *f->iffeature);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001661 if (!f->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01001662 LOGMEM;
1663 goto error;
1664 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001665 }
Radek Krejcie534c132016-11-23 13:32:31 +01001666 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01001667 /* some extensions may be already present from the substatements */
1668 reallocated = realloc(f->ext, (c_ext + f->ext_size) * sizeof *f->ext);
1669 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01001670 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001671 goto error;
1672 }
Radek Krejci5323b492017-01-16 15:40:11 +01001673 f->ext = reallocated;
1674
1675 /* init memory */
1676 memset(&f->ext[f->ext_size], 0, c_ext * sizeof *f->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001677 }
1678
Radek Krejcie534c132016-11-23 13:32:31 +01001679 LY_TREE_FOR_SAFE(yin->child, next, child) {
1680 if (strcmp(child->ns->value, LY_NSYIN)) {
1681 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01001682 ret = lyp_yin_fill_ext(f, LYEXT_PAR_FEATURE, 0, 0, module, child, &f->ext, f->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01001683 f->ext_size++;
1684 if (ret) {
1685 goto error;
1686 }
1687 } else { /* if-feature */
1688 ret = fill_yin_iffeature((struct lys_node *)f, 1, child, &f->iffeature[f->iffeature_size], unres);
1689 f->iffeature_size++;
1690 if (ret) {
1691 goto error;
1692 }
1693 }
1694 }
1695
Radek Krejcic79c6b12016-07-26 15:11:49 +02001696 /* check for circular dependencies */
1697 if (f->iffeature_size) {
1698 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1699 goto error;
1700 }
1701 }
1702
Radek Krejci3cf9e222015-06-18 11:37:50 +02001703 return EXIT_SUCCESS;
1704
1705error:
1706
1707 return EXIT_FAILURE;
1708}
1709
Michal Vasko0d343d12015-08-24 14:57:36 +02001710/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001711static int
Radek Krejcifccd1442017-01-16 10:26:57 +01001712fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must, struct unres_schema *unres)
Radek Krejci800af702015-06-02 13:46:01 +02001713{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001714 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001715
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001716 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001717 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001718 if (!must->expr) {
1719 goto error;
1720 }
Radek Krejci800af702015-06-02 13:46:01 +02001721
Radek Krejcifccd1442017-01-16 10:26:57 +01001722 return read_restr_substmt(module, LYEXT_PAR_MUST, must, yin, unres);
Radek Krejci800af702015-06-02 13:46:01 +02001723
Michal Vasko77dc5652016-02-15 12:32:42 +01001724error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001725 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001726}
1727
Radek Krejci581ce772015-11-10 17:22:40 +01001728static int
Michal Vasko88c29542015-11-27 14:57:53 +01001729fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1730 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001731{
1732 int i, j;
1733 const char *value, *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +02001734 struct unres_list_uniq *unique_info;
Radek Krejci581ce772015-11-10 17:22:40 +01001735
1736 /* get unique value (list of leafs supposed to be unique */
1737 GETVAL(value, yin, "tag");
1738
1739 /* count the number of unique leafs in the value */
1740 vaux = value;
1741 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001742 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001743 while (isspace(*vaux)) {
1744 vaux++;
1745 }
1746 }
1747 unique->expr_size++;
1748 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001749 if (!unique->expr) {
1750 LOGMEM;
1751 goto error;
1752 }
Radek Krejci581ce772015-11-10 17:22:40 +01001753
1754 for (i = 0; i < unique->expr_size; i++) {
1755 vaux = strpbrk(value, " \t\n");
1756 if (!vaux) {
1757 /* the last token, lydict_insert() will count its size on its own */
1758 vaux = value;
1759 }
1760
1761 /* store token into unique structure */
1762 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1763
1764 /* check that the expression does not repeat */
1765 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001766 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001767 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1768 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001769 goto error;
1770 }
1771 }
1772
1773 /* try to resolve leaf */
1774 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001775 unique_info = malloc(sizeof *unique_info);
1776 unique_info->list = parent;
1777 unique_info->expr = unique->expr[i];
1778 unique_info->trg_type = &unique->trg_type;
1779 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1){
Pavol Vican18b10212016-04-11 15:41:52 +02001780 goto error;
1781 }
Radek Krejci581ce772015-11-10 17:22:40 +01001782 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001783 if (resolve_unique(parent, unique->expr[i], &unique->trg_type)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001784 goto error;
1785 }
1786 }
1787
1788 /* move to next token */
1789 value = vaux;
1790 while(isspace(*value)) {
1791 value++;
1792 }
1793 }
1794
1795 return EXIT_SUCCESS;
1796
1797error:
1798 return EXIT_FAILURE;
1799}
1800
Michal Vasko0d343d12015-08-24 14:57:36 +02001801/* logs directly
1802 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001803 * type: 0 - min, 1 - max
1804 */
1805static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001806deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001807{
1808 const char *value;
1809 char *endptr;
1810 unsigned long val;
Pavol Vican09adcc32016-08-25 10:51:36 +02001811 uint32_t *ui32val, *min, *max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001812
Michal Vaskof7e57d52016-03-07 11:31:09 +01001813 /* del min/max is forbidden */
1814 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001815 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001816 goto error;
1817 }
1818
Radek Krejcieb00f512015-07-01 16:44:58 +02001819 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001820 if (target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001821 max = &((struct lys_node_leaflist *)target)->max;
1822 min = &((struct lys_node_leaflist *)target)->min;
Radek Krejci76512572015-08-04 09:47:08 +02001823 } else if (target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001824 max = &((struct lys_node_list *)target)->max;
1825 min = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001826 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001827 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1828 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001829 goto error;
1830 }
1831
1832 GETVAL(value, node, "value");
1833 while (isspace(value[0])) {
1834 value++;
1835 }
1836
Radek Krejci0d7b2472016-02-12 11:11:03 +01001837 if (type && !strcmp(value, "unbounded")) {
1838 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001839 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001840 ui32val = max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001841 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001842 /* convert it to uint32_t */
1843 errno = 0;
1844 endptr = NULL;
1845 val = strtoul(value, &endptr, 10);
1846 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001847 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001848 goto error;
1849 }
1850 if (type) {
1851 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001852 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001853 ui32val = max;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001854 } else {
1855 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001856 d->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001857 ui32val = min;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001858 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001859 }
1860
1861 if (d->mod == LY_DEVIATE_ADD) {
1862 /* check that there is no current value */
1863 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001864 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1865 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001866 goto error;
1867 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001868 } else if (d->mod == LY_DEVIATE_RPL) {
1869 /* unfortunately, there is no way to check reliably that there
1870 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02001871 }
1872
Michal Vaskof7e57d52016-03-07 11:31:09 +01001873 /* add (already checked) and replace */
1874 /* set new value specified in deviation */
1875 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02001876
Pavol Vican09adcc32016-08-25 10:51:36 +02001877 /* check min-elements is smaller than max-elements */
1878 if (*max && *min > *max) {
1879 if (type) {
Radek Krejci73f96012016-10-03 13:53:53 +02001880 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "max-elements");
Pavol Vican09adcc32016-08-25 10:51:36 +02001881 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
1882 } else {
Radek Krejci73f96012016-10-03 13:53:53 +02001883 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "min-elements");
Pavol Vican09adcc32016-08-25 10:51:36 +02001884 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
1885 }
1886 goto error;
1887 }
1888
Radek Krejcieb00f512015-07-01 16:44:58 +02001889 return EXIT_SUCCESS;
1890
1891error:
1892
1893 return EXIT_FAILURE;
1894}
1895
Michal Vasko0d343d12015-08-24 14:57:36 +02001896/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001897static int
Michal Vasko88c29542015-11-27 14:57:53 +01001898fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1899 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001900{
1901 const char *value, **stritem;
Radek Krejcie534c132016-11-23 13:32:31 +01001902 struct lyxml_elem *next, *next2, *child, *develem;
1903 int c_dev = 0, c_must, c_uniq, c_dflt, c_ext = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001904 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001905 int i, j, rc;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001906 unsigned int u;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001907 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001908 struct lys_deviate *d = NULL;
Radek Krejcie00d2312016-08-12 15:27:49 +02001909 struct lys_node *node = NULL, *parent, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001910 struct lys_node_choice *choice = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001911 struct lys_node_leaf *leaf = NULL;
1912 struct ly_set *dflt_check = ly_set_new();
Radek Krejcib8048692015-08-05 13:36:34 +02001913 struct lys_node_list *list = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001914 struct lys_node_leaflist *llist = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001915 struct lys_type *t = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001916 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001917 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01001918 struct unres_schema tmp_unres;
Radek Krejci27fe55e2016-09-13 17:13:35 +02001919 struct lys_module *mod;
Radek Krejcieb00f512015-07-01 16:44:58 +02001920
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001921 ctx = module->ctx;
1922
Radek Krejcieb00f512015-07-01 16:44:58 +02001923 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001924 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02001925 if (!dev->target_name) {
1926 goto error;
1927 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001928
1929 /* resolve target node */
Radek Krejcidf46e222016-11-08 11:57:37 +01001930 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1, (const struct lys_node **)&dev_target);
Michal Vasko60f4b452016-02-12 11:02:55 +01001931 if (rc || !dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001932 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001933 goto error;
1934 }
Radek Krejcic4283442016-04-22 09:19:27 +02001935 if (dev_target->module == lys_main_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001936 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
1937 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001938 goto error;
1939 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001940
1941 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01001942 if (!child->ns ) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001943 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001944 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001945 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01001946 } else if (strcmp(child->ns->value, LY_NSYIN)) {
1947 /* extension */
1948 c_ext++;
1949 continue;
1950 } else if (!strcmp(child->name, "description")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001951 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001952 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001953 goto error;
1954 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001955 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001956 if (!dev->dsc) {
1957 goto error;
1958 }
1959 } else if (!strcmp(child->name, "reference")) {
1960 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001961 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001962 goto error;
1963 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001964 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001965 if (!dev->ref) {
1966 goto error;
1967 }
1968 } else if (!strcmp(child->name, "deviate")) {
1969 c_dev++;
1970
Michal Vasko345da0a2015-12-02 10:35:55 +01001971 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001972 * further processed later
1973 */
1974 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001975
Radek Krejcieb00f512015-07-01 16:44:58 +02001976 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001977 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001978 goto error;
1979 }
1980
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001981 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001982 }
1983
1984 if (c_dev) {
1985 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001986 if (!dev->deviate) {
1987 LOGMEM;
1988 goto error;
1989 }
Pavol Vican09adcc32016-08-25 10:51:36 +02001990 } else {
1991 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
1992 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001993 }
Radek Krejcie534c132016-11-23 13:32:31 +01001994 if (c_ext) {
1995 dev->ext = calloc(c_ext, sizeof *dev->ext);
1996 if (!dev->ext) {
1997 LOGMEM;
1998 goto error;
1999 }
2000 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002001
Radek Krejcie534c132016-11-23 13:32:31 +01002002
2003 LY_TREE_FOR_SAFE(yin->child, next, develem) {
2004 if (strcmp(develem->ns->value, LY_NSYIN)) {
2005 /* deviation's extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01002006 rc = lyp_yin_fill_ext(dev, LYEXT_PAR_DEVIATION, 0, 0, module, develem, &dev->ext, dev->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01002007 dev->ext_size++;
2008 if (rc) {
2009 goto error;
2010 }
2011 continue;
2012 }
2013
2014 /* deviate */
Radek Krejcieb00f512015-07-01 16:44:58 +02002015 /* init */
2016 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002017 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002018 c_must = 0;
2019 c_uniq = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002020 c_dflt = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01002021 c_ext = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002022
2023 /* get deviation type */
2024 GETVAL(value, develem, "value");
2025 if (!strcmp(value, "not-supported")) {
2026 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
2027 /* no property expected in this case */
2028 if (develem->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002029 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002030 goto error;
2031 }
2032
Radek Krejci5b917642015-07-02 09:03:13 +02002033 /* and neither any other deviate statement is expected,
2034 * not-supported deviation must be the only deviation of the target
2035 */
2036 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002037 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2038 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02002039 goto error;
2040 }
2041
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002042 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02002043 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
2044 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
2045 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002046 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2047 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002048 goto error;
2049 }
2050 }
2051 }
Radek Krejci5b917642015-07-02 09:03:13 +02002052
Michal Vaskoff006c12016-02-17 11:15:19 +01002053 /* unlink and store the original node */
2054 lys_node_unlink(dev_target);
2055 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02002056
Radek Krejci5b917642015-07-02 09:03:13 +02002057 dev->deviate_size = 1;
Pavol Vican85991ec2016-08-16 14:58:12 +02002058 ly_set_free(dflt_check);
Radek Krejci5b917642015-07-02 09:03:13 +02002059 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02002060 } else if (!strcmp(value, "add")) {
2061 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
2062 } else if (!strcmp(value, "replace")) {
2063 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
2064 } else if (!strcmp(value, "delete")) {
2065 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
2066 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002067 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002068 goto error;
2069 }
2070 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01002071 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002072
Michal Vaskoff006c12016-02-17 11:15:19 +01002073 /* store a shallow copy of the original node */
2074 if (!dev->orig_node) {
2075 memset(&tmp_unres, 0, sizeof tmp_unres);
Radek Krejci6ff885d2017-01-03 14:06:22 +01002076 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, &tmp_unres, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01002077 /* just to be safe */
2078 if (tmp_unres.count) {
2079 LOGINT;
2080 goto error;
2081 }
2082 }
2083
Radek Krejcieb00f512015-07-01 16:44:58 +02002084 /* process deviation properties */
Radek Krejcie534c132016-11-23 13:32:31 +01002085 LY_TREE_FOR_SAFE(develem->child, next2, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002086 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2087 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002088 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002089 continue;
2090 }
2091
Radek Krejcieb00f512015-07-01 16:44:58 +02002092 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002093 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002094 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002095 goto error;
2096 }
2097
2098 /* for we deviate from RFC 6020 and allow config property even it is/is not
2099 * specified in the target explicitly since config property inherits. So we expect
2100 * that config is specified in every node. But for delete, we check that the value
2101 * is the same as here in deviation
2102 */
2103 GETVAL(value, child, "value");
2104 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002105 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02002106 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002107 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02002108 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002109 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002110 goto error;
2111 }
2112
2113 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002114 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002115 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002116 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002117 } else { /* add and replace are the same in this case */
2118 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01002119 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002120
2121 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01002122 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002123 }
2124 } else if (!strcmp(child->name, "default")) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002125 c_dflt++;
2126
2127 /* check target node type */
2128 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
2129 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2130 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
2131 goto error;
2132 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
2133 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2134 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
2135 goto error;
2136 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
2137 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2138 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002139 goto error;
2140 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002141
Radek Krejcid5a5c282016-08-15 15:38:08 +02002142 /* skip lyxml_free() at the end of the loop, this node will be processed later */
2143 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02002144
Radek Krejcieb00f512015-07-01 16:44:58 +02002145 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002146 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002147 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002148 goto error;
2149 }
2150
2151 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002152 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002153 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2154 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002155 goto error;
2156 }
2157
2158 GETVAL(value, child, "value");
2159 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002160 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002161 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002162 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002163 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002164 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002165 goto error;
2166 }
2167
2168 if (d->mod == LY_DEVIATE_ADD) {
2169 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01002170 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002171 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2172 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002173 goto error;
2174 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002175
Radek Krejci841ec082016-04-05 13:05:17 +02002176 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02002177 if (d->flags & LYS_MAND_TRUE) {
2178 if (dev_target->nodetype == LYS_CHOICE) {
2179 if (((struct lys_node_choice *)(dev_target))->dflt) {
2180 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2181 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2182 "Adding the \"mandatory\" statement is forbidden on choice with the \"default\" statement.");
2183 goto error;
2184 }
2185 } else if (dev_target->nodetype == LYS_LEAF) {
2186 if (((struct lys_node_leaf *)(dev_target))->dflt) {
2187 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2188 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2189 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
2190 goto error;
2191 }
2192 }
Radek Krejci841ec082016-04-05 13:05:17 +02002193 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002194
Michal Vasko21be1b32016-03-07 12:31:34 +01002195 dev_target->flags |= d->flags & LYS_MAND_MASK;
2196 } else if (d->mod == LY_DEVIATE_RPL) {
2197 /* check that there was a value before */
2198 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002199 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2200 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002201 goto error;
2202 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002203
Michal Vasko21be1b32016-03-07 12:31:34 +01002204 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01002205 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01002206 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002207 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002208 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002209 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002210 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002211
2212 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2213 for (parent = dev_target->parent;
2214 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2215 parent = parent->parent) {
2216 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2217 /* stop also on presence containers */
2218 break;
2219 }
2220 }
2221 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2222 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2223 if (lyp_check_mandatory_choice(parent)) {
2224 goto error;
2225 }
2226 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002227 } else if (!strcmp(child->name, "min-elements")) {
2228 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002229 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002230 goto error;
2231 }
2232 f_min = 1;
2233
Michal Vasko60f4b452016-02-12 11:02:55 +01002234 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002235 goto error;
2236 }
2237 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002238 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002239 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002240 goto error;
2241 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01002242 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02002243
Michal Vasko60f4b452016-02-12 11:02:55 +01002244 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002245 goto error;
2246 }
2247 } else if (!strcmp(child->name, "must")) {
2248 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002249 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002250 continue;
2251 } else if (!strcmp(child->name, "type")) {
2252 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002253 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002254 goto error;
2255 }
2256
Michal Vaskof7e57d52016-03-07 11:31:09 +01002257 /* add, del type is forbidden */
2258 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002259 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002260 goto error;
2261 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002262 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002263 goto error;
2264 }
2265
Radek Krejcieb00f512015-07-01 16:44:58 +02002266 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002267 if (dev_target->nodetype == LYS_LEAF) {
2268 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002269 if (((struct lys_node_leaf *)dev_target)->dflt) {
2270 ly_set_add(dflt_check, dev_target, 0);
2271 }
Michal Vasko60f4b452016-02-12 11:02:55 +01002272 } else if (dev_target->nodetype == LYS_LEAFLIST) {
2273 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002274 if (((struct lys_node_leaflist *)dev_target)->dflt) {
2275 ly_set_add(dflt_check, dev_target, 0);
2276 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002277 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002278 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2279 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002280 goto error;
2281 }
2282
Radek Krejcieb00f512015-07-01 16:44:58 +02002283 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002284 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01002285 /* HACK for unres */
2286 t->der = (struct lys_tpdf *)child;
Michal Vasko3767fb22016-07-21 12:10:57 +02002287 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002288 goto error;
2289 }
2290 d->type = t;
2291 } else if (!strcmp(child->name, "unique")) {
2292 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002293 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002294 continue;
2295 } else if (!strcmp(child->name, "units")) {
2296 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002297 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002298 goto error;
2299 }
2300
2301 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002302 if (dev_target->nodetype == LYS_LEAFLIST) {
2303 stritem = &((struct lys_node_leaflist *)dev_target)->units;
2304 } else if (dev_target->nodetype == LYS_LEAF) {
2305 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02002306 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002307 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2308 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002309 goto error;
2310 }
2311
2312 /* get units value */
2313 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002314 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02002315
2316 /* apply to target */
2317 if (d->mod == LY_DEVIATE_ADD) {
2318 /* check that there is no current value */
2319 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002320 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2321 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002322 goto error;
2323 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002324
Michal Vasko21be1b32016-03-07 12:31:34 +01002325 *stritem = lydict_insert(ctx, value, 0);
2326 } else if (d->mod == LY_DEVIATE_RPL) {
2327 /* check that there was a value before */
2328 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002329 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2330 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01002331 goto error;
2332 }
2333
2334 lydict_remove(ctx, *stritem);
2335 *stritem = lydict_insert(ctx, value, 0);
2336 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002337 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002338 if (!ly_strequal(*stritem, d->units, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002339 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2340 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002341 goto error;
2342 }
2343 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002344 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02002345 }
2346 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002347 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002348 goto error;
2349 }
2350
Michal Vasko88c29542015-11-27 14:57:53 +01002351 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002352 }
2353
2354 if (c_must) {
2355 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002356 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002357 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002358 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2359 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002360 break;
Radek Krejci76512572015-08-04 09:47:08 +02002361 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002362 trg_must = &((struct lys_node_container *)dev_target)->must;
2363 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002364 break;
Radek Krejci76512572015-08-04 09:47:08 +02002365 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002366 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2367 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002368 break;
Radek Krejci76512572015-08-04 09:47:08 +02002369 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002370 trg_must = &((struct lys_node_list *)dev_target)->must;
2371 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002372 break;
Radek Krejci76512572015-08-04 09:47:08 +02002373 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002374 case LYS_ANYDATA:
2375 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2376 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002377 break;
2378 default:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002379 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2380 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002381 goto error;
2382 }
2383
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002384 dev_target->flags &= ~LYS_XPATH_DEP;
Michal Vasko508a50d2016-09-07 14:50:33 +02002385
Radek Krejcieb00f512015-07-01 16:44:58 +02002386 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002387 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002388 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002389 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002390 } else if (d->mod == LY_DEVIATE_ADD) {
2391 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002392 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002393 if (!d->must) {
2394 LOGMEM;
2395 goto error;
2396 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002397 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02002398 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002399 d->must_size = c_must;
2400 } else { /* LY_DEVIATE_DEL */
2401 d->must = calloc(c_must, sizeof *d->must);
2402 }
Michal Vasko253035f2015-12-17 16:58:13 +01002403 if (!d->must) {
2404 LOGMEM;
2405 goto error;
2406 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002407 }
2408 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002409 /* replace unique is forbidden */
2410 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002411 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002412 goto error;
2413 }
2414
Radek Krejcieb00f512015-07-01 16:44:58 +02002415 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002416 if (dev_target->nodetype != LYS_LIST) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002417 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2418 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002419 goto error;
2420 }
2421
Michal Vasko60f4b452016-02-12 11:02:55 +01002422 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002423 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002424 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002425 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02002426 list->unique = d->unique;
2427 d->unique = &list->unique[list->unique_size];
2428 d->unique_size = c_uniq;
2429 } else { /* LY_DEVIATE_DEL */
2430 d->unique = calloc(c_uniq, sizeof *d->unique);
2431 }
Michal Vasko253035f2015-12-17 16:58:13 +01002432 if (!d->unique) {
2433 LOGMEM;
2434 goto error;
2435 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002436 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002437 if (c_dflt) {
2438 if (d->mod == LY_DEVIATE_ADD) {
2439 /* check that there is no current value */
2440 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
2441 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
2442 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2443 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
2444 goto error;
2445 }
2446
2447 /* check collision with mandatory/min-elements */
2448 if ((dev_target->flags & LYS_MAND_TRUE) ||
2449 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
2450 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2451 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2452 "Adding the \"default\" statement is forbidden on %s statement.",
2453 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2454 goto error;
2455 }
2456 } else if (d->mod == LY_DEVIATE_RPL) {
2457 /* check that there was a value before */
2458 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2459 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
2460 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2461 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
2462 goto error;
2463 }
2464 }
2465
2466 if (dev_target->nodetype == LYS_LEAFLIST) {
2467 /* reallocate default list in the target */
2468 llist = (struct lys_node_leaflist *)dev_target;
2469 if (d->mod == LY_DEVIATE_ADD) {
2470 /* reallocate (enlarge) the unique array of the target */
2471 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
2472 } else if (d->mod == LY_DEVIATE_RPL) {
2473 /* reallocate (replace) the unique array of the target */
2474 for (i = 0; i < llist->dflt_size; i++) {
2475 lydict_remove(llist->module->ctx, llist->dflt[i]);
2476 }
2477 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2478 llist->dflt_size = 0;
2479 }
2480 }
2481 d->dflt = calloc(c_dflt, sizeof *d->dflt);
2482 if (!d->dflt) {
2483 LOGMEM;
2484 goto error;
2485 }
2486 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002487
2488 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02002489 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002490 if (!strcmp(child->name, "must")) {
2491 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcifccd1442017-01-16 10:26:57 +01002492 if (fill_yin_must(module, child, &d->must[d->must_size], unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002493 goto error;
2494 }
2495
2496 /* find must to delete, we are ok with just matching conditions */
2497 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002498 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002499 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002500 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02002501 /* ... and maintain the array */
2502 (*trg_must_size)--;
2503 if (i != *trg_must_size) {
2504 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2505 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2506 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2507 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2508 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2509 }
2510 if (!(*trg_must_size)) {
2511 free(*trg_must);
2512 *trg_must = NULL;
2513 } else {
2514 (*trg_must)[*trg_must_size].expr = NULL;
2515 (*trg_must)[*trg_must_size].dsc = NULL;
2516 (*trg_must)[*trg_must_size].ref = NULL;
2517 (*trg_must)[*trg_must_size].eapptag = NULL;
2518 (*trg_must)[*trg_must_size].emsg = NULL;
2519 }
2520
2521 i = -1; /* set match flag */
2522 break;
2523 }
2524 }
2525 d->must_size++;
2526 if (i != -1) {
2527 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002528 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002529 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01002530 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002531 goto error;
2532 }
2533 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002534 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
Radek Krejcifccd1442017-01-16 10:26:57 +01002535 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]), unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002536 goto error;
2537 }
2538 (*trg_must_size)++;
2539 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002540
2541 /* check XPath dependencies again */
Michal Vaskoe8734262016-09-29 14:12:06 +02002542 if (*trg_must_size && unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02002543 goto error;
2544 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002545 } else if (!strcmp(child->name, "unique")) {
2546 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002547 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002548 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002549 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002550 goto error;
2551 }
2552
2553 /* find unique structures to delete */
2554 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002555 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002556 continue;
2557 }
2558
Radek Krejci581ce772015-11-10 17:22:40 +01002559 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002560 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002561 break;
2562 }
2563 }
2564
Radek Krejci581ce772015-11-10 17:22:40 +01002565 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002566 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002567 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002568 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002569 }
2570 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002571 /* ... and maintain the array */
2572 list->unique_size--;
2573 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002574 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2575 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002576 }
2577
2578 if (!list->unique_size) {
2579 free(list->unique);
2580 list->unique = NULL;
2581 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002582 list->unique[list->unique_size].expr_size = 0;
2583 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002584 }
2585
2586 i = -1; /* set match flag */
2587 break;
2588 }
2589 }
2590
2591 d->unique_size++;
2592 if (i != -1) {
2593 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002594 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2595 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002596 goto error;
2597 }
2598 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002599 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002600 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002601 list->unique_size++;
2602 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002603 goto error;
2604 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002605 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002606 } else if (!strcmp(child->name, "default")) {
2607 GETVAL(value, child, "value");
2608 u = strlen(value);
2609 d->dflt[d->dflt_size++] = lydict_insert(module->ctx, value, u);
2610
2611 if (dev_target->nodetype == LYS_CHOICE) {
2612 choice = (struct lys_node_choice *)dev_target;
2613 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2614 if (rc || !node) {
2615 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2616 goto error;
2617 }
2618 if (d->mod == LY_DEVIATE_DEL) {
2619 if (!choice->dflt || (choice->dflt != node)) {
2620 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2621 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2622 goto error;
2623 }
2624 } else { /* add or replace */
2625 choice->dflt = node;
2626 if (!choice->dflt) {
2627 /* default branch not found */
2628 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2629 goto error;
2630 }
2631 }
2632 } else if (dev_target->nodetype == LYS_LEAF) {
2633 leaf = (struct lys_node_leaf *)dev_target;
2634 if (d->mod == LY_DEVIATE_DEL) {
2635 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
2636 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2637 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2638 goto error;
2639 }
2640 /* remove value */
2641 lydict_remove(ctx, leaf->dflt);
2642 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01002643 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002644 } else { /* add (already checked) and replace */
2645 /* remove value */
2646 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01002647 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002648
2649 /* set new value */
2650 leaf->dflt = lydict_insert(ctx, value, u);
2651
Radek Krejcibd117f02016-11-04 16:28:08 +01002652 /* remember to check it later (it may not fit now, because the type can be deviated too) */
Radek Krejcid5a5c282016-08-15 15:38:08 +02002653 ly_set_add(dflt_check, dev_target, 0);
2654 }
2655 } else { /* LYS_LEAFLIST */
2656 llist = (struct lys_node_leaflist *)dev_target;
2657 if (d->mod == LY_DEVIATE_DEL) {
2658 /* find and remove the value in target list */
2659 for (i = 0; i < llist->dflt_size; i++) {
2660 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
2661 /* match, remove the value */
2662 lydict_remove(llist->module->ctx, llist->dflt[i]);
2663 llist->dflt[i] = NULL;
2664 break;
2665 }
2666 }
2667 if (i == llist->dflt_size) {
2668 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2669 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
2670 goto error;
2671 }
2672 } else {
2673 /* add or replace, anyway we place items into the deviate's list
2674 which propagates to the target */
2675 /* we just want to check that the value isn't already in the list */
2676 for (i = 0; i < llist->dflt_size; i++) {
2677 if (ly_strequal(llist->dflt[i], value, 1)) {
2678 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2679 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2680 goto error;
2681 }
2682 }
2683 /* store it in target node */
2684 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, u);
2685
2686 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2687 ly_set_add(dflt_check, dev_target, 0);
Radek Krejcibd117f02016-11-04 16:28:08 +01002688 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002689 }
2690 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002691 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002692 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002693
2694 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
2695 /* consolidate the final list in the target after removing items from it */
2696 llist = (struct lys_node_leaflist *)dev_target;
2697 for (i = j = 0; j < llist->dflt_size; j++) {
2698 llist->dflt[i] = llist->dflt[j];
2699 if (llist->dflt[i]) {
2700 i++;
2701 }
2702 }
2703 llist->dflt_size = i + 1;
2704 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002705 }
2706
Michal Vasko43a1feb2016-03-07 12:03:02 +01002707 /* now check whether default value, if any, matches the type */
Pavol Vican85991ec2016-08-16 14:58:12 +02002708 for (u = 0; u < dflt_check->number; ++u) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002709 value = NULL;
2710 rc = EXIT_SUCCESS;
2711 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2712 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
Radek Krejci51673202016-11-01 17:00:32 +01002713 value = leaf->dflt;
2714 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002715 } else { /* LYS_LEAFLIST */
2716 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2717 for (j = 0; j < llist->dflt_size; j++) {
Radek Krejci51673202016-11-01 17:00:32 +01002718 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2719 (struct lys_node *)(&llist->dflt[j]));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002720 if (rc == -1) {
Radek Krejci51673202016-11-01 17:00:32 +01002721 value = llist->dflt[j];
Radek Krejcid5a5c282016-08-15 15:38:08 +02002722 break;
2723 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002724 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002725
2726 }
2727 if (rc == -1) {
2728 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2729 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2730 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2731 dev->target_name);
2732 goto error;
Michal Vasko43a1feb2016-03-07 12:03:02 +01002733 }
2734 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002735
Radek Krejci27fe55e2016-09-13 17:13:35 +02002736 /* mark all the affected modules as deviated and implemented */
2737 for(parent = dev_target; parent; parent = lys_parent(parent)) {
2738 mod = lys_node_module(parent);
2739 if (module != mod) {
2740 mod->deviated = 1;
2741 lys_set_implemented(mod);
2742 }
2743 }
2744
Radek Krejcid5a5c282016-08-15 15:38:08 +02002745 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002746 return EXIT_SUCCESS;
2747
2748error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002749 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002750 return EXIT_FAILURE;
2751}
2752
Michal Vasko0d343d12015-08-24 14:57:36 +02002753/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002754static int
Radek Krejcib8048692015-08-05 13:36:34 +02002755fill_yin_augment(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_node_augment *aug,
Michal Vaskof02e3742015-08-05 16:27:02 +02002756 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02002757{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002758 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01002759 struct lyxml_elem *sub, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002760 struct lys_node *node;
Radek Krejcie534c132016-11-23 13:32:31 +01002761 int ret, c_ftrs = 0, c_ext = 0;
Radek Krejci106efc02015-06-10 14:36:27 +02002762
Michal Vasko591e0b22015-08-13 13:53:43 +02002763 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002764 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002765 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02002766 if (!aug->target_name) {
2767 goto error;
2768 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002769 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02002770
Radek Krejci07d0fb92017-01-13 14:11:05 +01002771 if (read_yin_common(module, NULL, aug, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002772 goto error;
2773 }
2774
Radek Krejcie534c132016-11-23 13:32:31 +01002775 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2776 if (strcmp(sub->ns->value, LY_NSYIN)) {
2777 /* extension */
2778 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02002779 continue;
2780 }
2781
Radek Krejcie534c132016-11-23 13:32:31 +01002782 if (!strcmp(sub->name, "if-feature")) {
2783 c_ftrs++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002784 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01002785 } else if (!strcmp(sub->name, "when")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002786 if (aug->when) {
Radek Krejcie534c132016-11-23 13:32:31 +01002787 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002788 goto error;
2789 }
2790
Radek Krejci5323b492017-01-16 15:40:11 +01002791 aug->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002792 if (!aug->when) {
Radek Krejcie534c132016-11-23 13:32:31 +01002793 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002794 goto error;
2795 }
Radek Krejcie534c132016-11-23 13:32:31 +01002796 lyxml_free(module->ctx, sub);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002797 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002798
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002799 /* check allowed data sub-statements */
Radek Krejcie534c132016-11-23 13:32:31 +01002800 } else if (!strcmp(sub->name, "container")) {
2801 node = read_yin_container(module, (struct lys_node *)aug, sub, 1, unres);
2802 } else if (!strcmp(sub->name, "leaf-list")) {
2803 node = read_yin_leaflist(module, (struct lys_node *)aug, sub, 1, unres);
2804 } else if (!strcmp(sub->name, "leaf")) {
2805 node = read_yin_leaf(module, (struct lys_node *)aug, sub, 1, unres);
2806 } else if (!strcmp(sub->name, "list")) {
2807 node = read_yin_list(module, (struct lys_node *)aug, sub, 1, unres);
2808 } else if (!strcmp(sub->name, "uses")) {
2809 node = read_yin_uses(module, (struct lys_node *)aug, sub, unres);
2810 } else if (!strcmp(sub->name, "choice")) {
2811 node = read_yin_choice(module, (struct lys_node *)aug, sub, 1, unres);
2812 } else if (!strcmp(sub->name, "case")) {
2813 node = read_yin_case(module, (struct lys_node *)aug, sub, 1, unres);
2814 } else if (!strcmp(sub->name, "anyxml")) {
2815 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYXML, 1, unres);
2816 } else if (!strcmp(sub->name, "anydata")) {
2817 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYDATA, 1, unres);
2818 } else if (!strcmp(sub->name, "action")) {
2819 node = read_yin_rpc_action(module, (struct lys_node *)aug, sub, unres);
2820 } else if (!strcmp(sub->name, "notification")) {
2821 node = read_yin_notif(module, (struct lys_node *)aug, sub, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002822 } else {
Radek Krejcie534c132016-11-23 13:32:31 +01002823 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002824 goto error;
2825 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002826
Radek Krejci1d82ef62015-08-07 14:44:40 +02002827 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002828 goto error;
2829 }
2830
Radek Krejci1d82ef62015-08-07 14:44:40 +02002831 node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01002832 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002833 }
2834
Radek Krejcie534c132016-11-23 13:32:31 +01002835 if (c_ftrs) {
2836 aug->iffeature = calloc(c_ftrs, sizeof *aug->iffeature);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002837 if (!aug->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002838 LOGMEM;
2839 goto error;
2840 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002841 }
Radek Krejcie534c132016-11-23 13:32:31 +01002842 if (c_ext) {
2843 aug->ext = calloc(c_ext, sizeof *aug->ext);
2844 if (!aug->ext) {
2845 LOGMEM;
2846 goto error;
2847 }
2848 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002849
Radek Krejcie534c132016-11-23 13:32:31 +01002850 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2851 if (strcmp(sub->ns->value, LY_NSYIN)) {
2852 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01002853 ret = lyp_yin_fill_ext(aug, LYEXT_PAR_NODE, 0, 0, module, sub, &aug->ext, aug->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01002854 aug->ext_size++;
2855 if (ret) {
2856 goto error;
2857 }
2858 } else if (!strcmp(sub->name, "if-feature")) {
2859 ret = fill_yin_iffeature((struct lys_node *)aug, 0, sub, &aug->iffeature[aug->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002860 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002861 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002862 goto error;
2863 }
Radek Krejcie534c132016-11-23 13:32:31 +01002864 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002865 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002866 }
2867
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002868 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002869 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02002870 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02002871 * when the uses does and cannot be resolved now for sure
2872 * (the grouping was not yet copied into uses).
2873 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02002874 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002875 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002876 goto error;
2877 }
Michal Vasko49291b32015-08-06 09:49:41 +02002878 }
Radek Krejci106efc02015-06-10 14:36:27 +02002879
Michal Vasko508a50d2016-09-07 14:50:33 +02002880 /* check XPath dependencies */
2881 if (aug->when && (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1)) {
2882 goto error;
2883 }
2884
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002885 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002886
2887error:
2888
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002889 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002890}
2891
Michal Vasko0d343d12015-08-24 14:57:36 +02002892/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002893static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02002894fill_yin_refine(struct lys_node *uses, struct lyxml_elem *yin, struct lys_refine *rfn, struct unres_schema *unres)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002895{
Radek Krejci363bd4a2016-07-29 14:30:20 +02002896 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002897 struct lyxml_elem *sub, *next;
2898 const char *value;
2899 char *endptr;
2900 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01002901 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002902 int r;
2903 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002904
Radek Krejci363bd4a2016-07-29 14:30:20 +02002905 assert(uses);
2906 module = uses->module; /* shorthand */
2907
Radek Krejci07d0fb92017-01-13 14:11:05 +01002908 if (read_yin_common(module, NULL, rfn, LYEXT_PAR_REFINE, yin, OPT_CFG_PARSE | OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002909 goto error;
2910 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002911
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002912 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002913 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002914 if (!rfn->target_name) {
2915 goto error;
2916 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002917
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002918 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01002919 if (strcmp(sub->ns->value, LY_NSYIN)) {
2920 /* extension */
2921 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02002922 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02002923
Radek Krejcie534c132016-11-23 13:32:31 +01002924 } else if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02002925 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02002926
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002927 /* check possibility of statements combination */
2928 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02002929 if (c_dflt) {
2930 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002931 if (module->version < 2) {
2932 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
2933 goto error;
2934 }
Radek Krejci200bf712016-08-16 17:11:04 +02002935 rfn->target_type &= LYS_LEAFLIST;
2936 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002937 if (module->version < 2) {
2938 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
2939 } else {
2940 /* YANG 1.1 */
2941 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
2942 }
Radek Krejci200bf712016-08-16 17:11:04 +02002943 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002944 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002945 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2946 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002947 goto error;
2948 }
2949 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002950 if (module->version < 2) {
2951 rfn->target_type = LYS_LEAF | LYS_CHOICE;
2952 } else {
2953 /* YANG 1.1 */
2954 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
2955 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002956 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002957
Radek Krejci200bf712016-08-16 17:11:04 +02002958 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002959 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002960 } else if (!strcmp(sub->name, "mandatory")) {
2961 /* leaf, choice or anyxml */
2962 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002963 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002964 goto error;
2965 }
2966 /* just checking the flags in leaf is not sufficient, we would allow
2967 * multiple mandatory statements with the "false" value
2968 */
2969 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002970
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002971 /* check possibility of statements combination */
2972 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002973 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002974 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002975 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2976 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002977 goto error;
2978 }
2979 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002980 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002981 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002982
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002983 GETVAL(value, sub, "value");
2984 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002985 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002986 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002987 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002988 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002989 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002990 goto error;
2991 }
2992 } else if (!strcmp(sub->name, "min-elements")) {
2993 /* list or leaf-list */
2994 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002995 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002996 goto error;
2997 }
2998 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002999
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003000 /* check possibility of statements combination */
3001 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003002 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003003 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003004 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3005 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003006 goto error;
3007 }
3008 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003009 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003010 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003011
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003012 GETVAL(value, sub, "value");
3013 while (isspace(value[0])) {
3014 value++;
3015 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003016
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003017 /* convert it to uint32_t */
3018 errno = 0;
3019 endptr = NULL;
3020 val = strtoul(value, &endptr, 10);
3021 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003022 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003023 goto error;
3024 }
3025 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003026 rfn->flags |= LYS_RFN_MINSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003027 } else if (!strcmp(sub->name, "max-elements")) {
3028 /* list or leaf-list */
3029 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003030 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003031 goto error;
3032 }
3033 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003034
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003035 /* check possibility of statements combination */
3036 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003037 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003038 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003039 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3040 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003041 goto error;
3042 }
3043 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003044 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003045 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003046
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003047 GETVAL(value, sub, "value");
3048 while (isspace(value[0])) {
3049 value++;
3050 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003051
Radek Krejci0d7b2472016-02-12 11:11:03 +01003052 if (!strcmp(value, "unbounded")) {
3053 rfn->mod.list.max = 0;
3054 } else {
3055 /* convert it to uint32_t */
3056 errno = 0;
3057 endptr = NULL;
3058 val = strtoul(value, &endptr, 10);
3059 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003060 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003061 goto error;
3062 }
3063 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003064 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003065 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003066 } else if (!strcmp(sub->name, "presence")) {
3067 /* container */
3068 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003069 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003070 goto error;
3071 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003073 /* check possibility of statements combination */
3074 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003075 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003076 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003077 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3078 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003079 goto error;
3080 }
3081 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003082 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003083 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003084
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003085 GETVAL(value, sub, "value");
3086 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
3087 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02003088 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003089 /* check possibility of statements combination */
3090 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003091 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003092 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003093 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3094 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003095 goto error;
3096 }
3097 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003098 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003099 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003100
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003101 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003102 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003103
Radek Krejci363bd4a2016-07-29 14:30:20 +02003104 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
3105 /* leaf, leaf-list, list, container or anyxml */
3106 /* check possibility of statements combination */
3107 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003108 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003109 if (!rfn->target_type) {
3110 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3111 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
3112 goto error;
3113 }
3114 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003115 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003116 }
3117
3118 c_ftrs++;
3119 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003120 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003121 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003122 goto error;
3123 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003124
Michal Vasko345da0a2015-12-02 10:35:55 +01003125 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003126 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003127
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003128 /* process nodes with cardinality of 0..n */
3129 if (c_must) {
3130 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003131 if (!rfn->must) {
3132 LOGMEM;
3133 goto error;
3134 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003135 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02003136 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02003137 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003138 if (!rfn->iffeature) {
3139 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02003140 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003141 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003142 }
Radek Krejci200bf712016-08-16 17:11:04 +02003143 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003144 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Radek Krejci200bf712016-08-16 17:11:04 +02003145 if (!rfn->dflt) {
3146 LOGMEM;
3147 goto error;
3148 }
3149 }
Radek Krejcie534c132016-11-23 13:32:31 +01003150 if (c_ext) {
3151 rfn->ext = calloc(c_ext, sizeof *rfn->ext);
3152 if (!rfn->ext) {
3153 LOGMEM;
3154 goto error;
3155 }
3156 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003157
Radek Krejcie534c132016-11-23 13:32:31 +01003158 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3159 if (strcmp(sub->ns->value, LY_NSYIN)) {
3160 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003161 r = lyp_yin_fill_ext(rfn, LYEXT_PAR_REFINE, 0, 0, module, sub, &rfn->ext, rfn->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003162 rfn->ext_size++;
3163 if (r) {
3164 goto error;
3165 }
3166 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003167 r = fill_yin_iffeature(uses, 0, sub, &rfn->iffeature[rfn->iffeature_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003168 rfn->iffeature_size++;
3169 if (r) {
3170 goto error;
3171 }
Radek Krejci200bf712016-08-16 17:11:04 +02003172 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01003173 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003174 rfn->must_size++;
3175 if (r) {
3176 goto error;
3177 }
Radek Krejci200bf712016-08-16 17:11:04 +02003178 } else { /* default */
3179 GETVAL(value, sub, "value");
3180
3181 /* check for duplicity */
3182 for (r = 0; r < rfn->dflt_size; r++) {
3183 if (ly_strequal(rfn->dflt[r], value, 1)) {
3184 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3185 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
3186 goto error;
3187 }
3188 }
3189 rfn->dflt[rfn->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02003190 }
3191 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003192
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003193 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003194
3195error:
3196
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003197 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003198}
3199
Michal Vasko0d343d12015-08-24 14:57:36 +02003200/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003201static int
Radek Krejcie534c132016-11-23 13:32:31 +01003202fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02003203{
Radek Krejcie534c132016-11-23 13:32:31 +01003204 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003205 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003206 int r, c_ext = 0;
Radek Krejciefaeba32015-05-27 14:30:57 +02003207
Radek Krejcie534c132016-11-23 13:32:31 +01003208 /* init */
3209 memset(&exts, 0, sizeof exts);
3210
3211 LY_TREE_FOR_SAFE(yin->child, next, child) {
3212 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003213 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003214 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003215 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3216 /* extension */
3217 c_ext++;
3218 lyxml_unlink_elem(module->ctx, child, 2);
3219 lyxml_add_child(module->ctx, &exts, child);
3220 } else if (!strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003221 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01003222 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003223 goto error;
3224 }
3225 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
3226 } else if (!strcmp(child->name, "revision-date")) {
3227 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02003228 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3229 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003230 }
3231 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003232 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003233 goto error;
3234 }
3235 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci1a31efe2016-07-29 11:04:16 +02003236 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003237 if (imp->dsc) {
3238 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3239 goto error;
3240 }
3241 imp->dsc = read_yin_subnode(module->ctx, child, "text");
3242 if (!imp->dsc) {
3243 goto error;
3244 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003245 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003246 if (imp->ref) {
3247 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3248 goto error;
3249 }
3250 imp->ref = read_yin_subnode(module->ctx, child, "text");
3251 if (!imp->ref) {
3252 goto error;
3253 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003254 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003255 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003256 goto error;
3257 }
3258 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003259
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003260 /* check mandatory information */
3261 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003262 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003263 goto error;
3264 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003265
Radek Krejcie534c132016-11-23 13:32:31 +01003266 /* process extensions */
3267 if (c_ext) {
3268 imp->ext = calloc(c_ext, sizeof *imp->ext);
3269 if (!imp->ext) {
3270 LOGMEM;
3271 goto error;
3272 }
3273 LY_TREE_FOR_SAFE(exts.child, next, child) {
3274 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003275 r = lyp_yin_fill_ext(imp, LYEXT_PAR_IMPORT, 0, 0, module, child, &imp->ext, imp->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003276 imp->ext_size++;
3277 if (r) {
3278 goto error;
3279 }
3280 }
3281 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003282
Radek Krejcie534c132016-11-23 13:32:31 +01003283 GETVAL(value, yin, "module");
Pavol Vicane994fda2016-03-22 10:47:58 +01003284 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02003285
3286error:
3287
Radek Krejcie534c132016-11-23 13:32:31 +01003288 while (exts.child) {
3289 lyxml_free(module->ctx, exts.child);
3290 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003291 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02003292}
3293
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003294/* logs directly
3295 * returns:
3296 * 0 - inc successfully filled
3297 * -1 - error, inc is cleaned
3298 * 1 - duplication, ignore the inc structure, inc is cleaned
3299 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003300static int
Michal Vasko5ff78822016-02-12 09:33:31 +01003301fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
3302 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02003303{
Radek Krejcie534c132016-11-23 13:32:31 +01003304 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003305 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003306 int r, c_ext = 0;
Radek Krejciefaeba32015-05-27 14:30:57 +02003307
Radek Krejcie534c132016-11-23 13:32:31 +01003308 /* init */
3309 memset(&exts, 0, sizeof exts);
3310
3311 LY_TREE_FOR_SAFE(yin->child, next, child) {
3312 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003313 /* garbage */
3314 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003315 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3316 /* extension */
3317 c_ext++;
3318 lyxml_unlink_elem(module->ctx, child, 2);
3319 lyxml_add_child(module->ctx, &exts, child);
3320 } else if (!strcmp(child->name, "revision-date")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003321 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003322 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003323 goto error;
3324 }
3325 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003326 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003327 goto error;
3328 }
3329 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci1a31efe2016-07-29 11:04:16 +02003330 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003331 if (inc->dsc) {
3332 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3333 goto error;
3334 }
3335 inc->dsc = read_yin_subnode(module->ctx, child, "text");
3336 if (!inc->dsc) {
3337 goto error;
3338 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003339 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003340 if (inc->ref) {
3341 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3342 goto error;
3343 }
3344 inc->ref = read_yin_subnode(module->ctx, child, "text");
3345 if (!inc->ref) {
3346 goto error;
3347 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003348 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003349 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003350 goto error;
3351 }
3352 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003353
Radek Krejcie534c132016-11-23 13:32:31 +01003354 /* process extensions */
3355 if (c_ext) {
3356 inc->ext = calloc(c_ext, sizeof *inc->ext);
3357 if (!inc->ext) {
3358 LOGMEM;
3359 goto error;
3360 }
3361 LY_TREE_FOR_SAFE(exts.child, next, child) {
3362 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003363 r = lyp_yin_fill_ext(inc, LYEXT_PAR_INCLUDE, 0, 0, module, child, &inc->ext, inc->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003364 inc->ext_size++;
3365 if (r) {
3366 goto error;
3367 }
3368 }
3369 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003370
Radek Krejcie534c132016-11-23 13:32:31 +01003371 GETVAL(value, yin, "module");
Pavol Vican0adf01d2016-03-22 12:29:33 +01003372 return lyp_check_include(module, submodule, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02003373
3374error:
3375
Radek Krejci83e3f5b2016-06-24 14:55:25 +02003376 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02003377}
3378
Michal Vasko0d343d12015-08-24 14:57:36 +02003379/* logs directly
3380 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003381 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02003382 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02003383 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003384 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003385static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01003386read_yin_common(struct lys_module *module, struct lys_node *parent, void *stmt, LYEXT_PAR stmt_type,
3387 struct lyxml_elem *xmlnode, int opt, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003388{
Radek Krejci07d0fb92017-01-13 14:11:05 +01003389 struct lys_node *node = stmt;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003390 const char *value;
3391 struct lyxml_elem *sub, *next;
3392 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003393
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003394 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003395 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003396 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003397
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003398 if (opt & OPT_IDENT) {
3399 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01003400 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003401 goto error;
3402 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003403 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003404 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003405
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003406 /* process local parameters */
3407 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003408 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003409 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003410 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02003411 continue;
3412 }
3413 if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejci6ff885d2017-01-03 14:06:22 +01003414 /* possibly an extension, keep the node for later processing, so skipping lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003415 continue;
3416 }
3417
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003418 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003419 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003420 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003421 goto error;
3422 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003423
Radek Krejciac00b2a2017-01-17 14:05:00 +01003424 if (read_yin_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003425 goto error;
3426 }
3427
Radek Krejci1d82ef62015-08-07 14:44:40 +02003428 node->dsc = read_yin_subnode(ctx, sub, "text");
3429 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003430 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003431 }
3432 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003433 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003434 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003435 goto error;
3436 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003437
Radek Krejciac00b2a2017-01-17 14:05:00 +01003438 if (read_yin_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003439 goto error;
3440 }
3441
Radek Krejci1d82ef62015-08-07 14:44:40 +02003442 node->ref = read_yin_subnode(ctx, sub, "text");
3443 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003444 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003445 }
3446 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003447 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003448 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003449 goto error;
3450 }
3451 GETVAL(value, sub, "value");
3452 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003453 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003454 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003455 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003456 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003457 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003458 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003459 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003460 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003461 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003462
Radek Krejciac00b2a2017-01-17 14:05:00 +01003463 if (read_yin_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_STATUS, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003464 goto error;
3465 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003466 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3467 if (opt & OPT_CFG_PARSE) {
3468 if (node->flags & LYS_CONFIG_MASK) {
3469 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
3470 goto error;
3471 }
3472 GETVAL(value, sub, "value");
3473 if (!strcmp(value, "false")) {
3474 node->flags |= LYS_CONFIG_R;
3475 } else if (!strcmp(value, "true")) {
3476 node->flags |= LYS_CONFIG_W;
3477 } else {
3478 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3479 goto error;
3480 }
3481 node->flags |= LYS_CONFIG_SET;
Radek Krejci07d0fb92017-01-13 14:11:05 +01003482
Radek Krejciac00b2a2017-01-17 14:05:00 +01003483 if (read_yin_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003484 goto error;
3485 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003486 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003487 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003488 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003489 continue;
3490 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003491 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003492 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003493
Michal Vaskoe022a562016-09-27 14:24:15 +02003494 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003495 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02003496 if (parent) {
3497 node->flags |= parent->flags & LYS_CONFIG_MASK;
3498 } else if (!parent) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003499 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003500 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003501 }
3502 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003503
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003504 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02003505
3506error:
3507
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003508 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003509}
3510
Michal Vasko0d343d12015-08-24 14:57:36 +02003511/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003512static struct lys_when *
Radek Krejci5323b492017-01-16 15:40:11 +01003513read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003514{
Radek Krejci76512572015-08-04 09:47:08 +02003515 struct lys_when *retval = NULL;
Radek Krejci5323b492017-01-16 15:40:11 +01003516 struct lyxml_elem *child, *next;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003517 const char *value;
3518
3519 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01003520 if (!retval) {
3521 LOGMEM;
3522 return NULL;
3523 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003524
3525 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01003526 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02003527 if (!retval->cond) {
3528 goto error;
3529 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003530
Radek Krejci5323b492017-01-16 15:40:11 +01003531 LY_TREE_FOR_SAFE(yin->child, next, child) {
3532 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003533 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003534 continue;
Radek Krejci5323b492017-01-16 15:40:11 +01003535 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3536 /* extensions */
Radek Krejciac00b2a2017-01-17 14:05:00 +01003537 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003538 goto error;
3539 }
3540 } else if (!strcmp(child->name, "description")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003541 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003542 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003543 goto error;
3544 }
Radek Krejci5323b492017-01-16 15:40:11 +01003545
Radek Krejciac00b2a2017-01-17 14:05:00 +01003546 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003547 goto error;
3548 }
3549
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003550 retval->dsc = read_yin_subnode(module->ctx, child, "text");
3551 if (!retval->dsc) {
3552 goto error;
3553 }
3554 } else if (!strcmp(child->name, "reference")) {
3555 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003556 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003557 goto error;
3558 }
Radek Krejci5323b492017-01-16 15:40:11 +01003559
Radek Krejciac00b2a2017-01-17 14:05:00 +01003560 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003561 goto error;
3562 }
3563
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003564 retval->ref = read_yin_subnode(module->ctx, child, "text");
3565 if (!retval->ref) {
3566 goto error;
3567 }
3568 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003569 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003570 goto error;
3571 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003572 }
3573
3574 return retval;
3575
3576error:
3577
Michal Vasko0308dd62015-10-07 09:14:40 +02003578 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003579 return NULL;
3580}
3581
Michal Vasko0d343d12015-08-24 14:57:36 +02003582/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003583static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003584read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02003585 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02003586{
Michal Vasko29fc0182015-08-24 15:02:39 +02003587 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003588 struct lys_node_case *cs;
3589 struct lys_node *retval, *node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01003590 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003591
Radek Krejcie867c852015-08-27 09:52:34 +02003592 /* init */
3593 memset(&root, 0, sizeof root);
3594
Radek Krejci1d82ef62015-08-07 14:44:40 +02003595 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01003596 if (!cs) {
3597 LOGMEM;
3598 return NULL;
3599 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003600 cs->nodetype = LYS_CASE;
3601 cs->prev = (struct lys_node *)cs;
3602 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003603
Radek Krejci07d0fb92017-01-13 14:11:05 +01003604 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
3605 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_INHERIT : 0), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003606 goto error;
3607 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003608
Radek Krejcia9544502015-08-14 08:24:29 +02003609 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3610
Michal Vasko3a0043f2015-08-12 12:11:30 +02003611 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003612 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003613 goto error;
3614 }
3615
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003616 /* process choice's specific children */
3617 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01003618 if (strcmp(sub->ns->value, LY_NSYIN)) {
3619 /* extension */
3620 c_ext++;
3621 } else if (!strcmp(sub->name, "container") ||
Michal Vasko29fc0182015-08-24 15:02:39 +02003622 !strcmp(sub->name, "leaf-list") ||
3623 !strcmp(sub->name, "leaf") ||
3624 !strcmp(sub->name, "list") ||
3625 !strcmp(sub->name, "uses") ||
3626 !strcmp(sub->name, "choice") ||
3627 !strcmp(sub->name, "anyxml")) {
3628
Michal Vaskof3930de2015-10-22 12:03:59 +02003629 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02003630 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003631 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02003632 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003633 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003634 if (cs->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003635 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003636 goto error;
3637 }
3638
Radek Krejci5323b492017-01-16 15:40:11 +01003639 cs->when = read_yin_when(module, sub, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02003640 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003641 goto error;
3642 }
Michal Vasko29fc0182015-08-24 15:02:39 +02003643
Michal Vasko345da0a2015-12-02 10:35:55 +01003644 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003645 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003646 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003647 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003648 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003649 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003650
Radek Krejci3cf9e222015-06-18 11:37:50 +02003651 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003652 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
3653 if (!cs->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003654 LOGMEM;
3655 goto error;
3656 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003657 }
Radek Krejcie534c132016-11-23 13:32:31 +01003658 if (c_ext) {
3659 cs->ext = calloc(c_ext, sizeof *cs->ext);
3660 if (!cs->ext) {
3661 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003662 goto error;
3663 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003664 }
Radek Krejcie534c132016-11-23 13:32:31 +01003665 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3666 if (strcmp(sub->ns->value, LY_NSYIN)) {
3667 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003668 ret = lyp_yin_fill_ext(retval, LYEXT_PAR_NODE, 0, 0, module, sub, &retval->ext, retval->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003669 retval->ext_size++;
3670 if (ret) {
3671 goto error;
3672 }
3673 } else {
3674 /* if-feature */
3675 ret = fill_yin_iffeature(retval, 0, sub, &cs->iffeature[cs->iffeature_size], unres);
3676 cs->iffeature_size++;
3677 if (ret) {
3678 goto error;
3679 }
3680 }
3681 }
Radek Krejcib388c152015-06-04 17:03:03 +02003682
Michal Vasko29fc0182015-08-24 15:02:39 +02003683 /* last part - process data nodes */
3684 LY_TREE_FOR_SAFE(root.child, next, sub) {
3685 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003686 node = read_yin_container(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003687 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003688 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003689 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003690 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003691 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003692 node = read_yin_list(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003693 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003694 node = read_yin_choice(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003695 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003696 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003697 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003698 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02003699 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003700 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003701 }
3702 if (!node) {
3703 goto error;
3704 }
3705
Michal Vasko345da0a2015-12-02 10:35:55 +01003706 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02003707 }
3708
Michal Vasko508a50d2016-09-07 14:50:33 +02003709 /* check XPath dependencies */
3710 if (cs->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3711 goto error;
3712 }
3713
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003714 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003715
3716error:
3717
Michal Vasko29fc0182015-08-24 15:02:39 +02003718 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003719 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02003720 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003721 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02003722
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003723 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003724}
3725
Michal Vasko0d343d12015-08-24 14:57:36 +02003726/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003727static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003728read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
3729 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003730{
Radek Krejci629cdef2016-06-06 15:06:36 +02003731 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003732 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003733 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02003734 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02003735 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003736 int f_mand = 0, c_ftrs = 0, c_ext = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003737
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003738 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01003739 if (!choice) {
3740 LOGMEM;
3741 return NULL;
3742 }
Radek Krejci76512572015-08-04 09:47:08 +02003743 choice->nodetype = LYS_CHOICE;
3744 choice->prev = (struct lys_node *)choice;
3745 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003746
Radek Krejci07d0fb92017-01-13 14:11:05 +01003747 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
3748 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003749 goto error;
3750 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003751
Radek Krejcia9544502015-08-14 08:24:29 +02003752 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3753
Michal Vasko3a0043f2015-08-12 12:11:30 +02003754 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003755 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003756 goto error;
3757 }
3758
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003759 /* process choice's specific children */
3760 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01003761 if (strcmp(sub->ns->value, LY_NSYIN)) {
3762 /* extension */
3763 c_ext++;
3764 /* keep it for later processing, skip lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003765 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003766 } else if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003767 if (!(node = read_yin_container(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003768 goto error;
3769 }
3770 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003771 if (!(node = read_yin_leaflist(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003772 goto error;
3773 }
3774 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003775 if (!(node = read_yin_leaf(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003776 goto error;
3777 }
3778 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003779 if (!(node = read_yin_list(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003780 goto error;
3781 }
3782 } else if (!strcmp(sub->name, "case")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003783 if (!(node = read_yin_case(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003784 goto error;
3785 }
3786 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003787 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003788 goto error;
3789 }
3790 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003791 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003792 goto error;
3793 }
3794 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02003795 if (dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003796 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003797 goto error;
3798 }
Radek Krejci629cdef2016-06-06 15:06:36 +02003799 dflt = sub;
3800 lyxml_unlink_elem(ctx, dflt, 0);
3801
Radek Krejcif9a312c2016-06-06 15:14:30 +02003802 continue;
3803 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
3804
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003805 } else if (!strcmp(sub->name, "mandatory")) {
3806 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003807 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003808 goto error;
3809 }
3810 /* just checking the flags in leaf is not sufficient, we would allow
3811 * multiple mandatory statements with the "false" value
3812 */
3813 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003814
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003815 GETVAL(value, sub, "value");
3816 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003817 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003818 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003819 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003820 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003821 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003822 goto error;
3823 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003824 } else if (!strcmp(sub->name, "when")) {
3825 if (choice->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003826 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003827 goto error;
3828 }
3829
Radek Krejci5323b492017-01-16 15:40:11 +01003830 choice->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003831 if (!choice->when) {
3832 goto error;
3833 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003834 } else if (!strcmp(sub->name, "if-feature")) {
3835 c_ftrs++;
3836
Michal Vasko345da0a2015-12-02 10:35:55 +01003837 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02003838 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02003839 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003840 if (!(node = read_yin_choice(module, retval, sub, valid_config, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02003841 goto error;
3842 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003843 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003844 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003845 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003846 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003847
Radek Krejci1d82ef62015-08-07 14:44:40 +02003848 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01003849 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003850 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003851
Radek Krejci3cf9e222015-06-18 11:37:50 +02003852 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003853 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
3854 if (!choice->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003855 LOGMEM;
3856 goto error;
3857 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003858 }
Radek Krejcie534c132016-11-23 13:32:31 +01003859 if (c_ext) {
3860 choice->ext = calloc(c_ext, sizeof *choice->ext);
3861 if (!choice->ext) {
3862 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003863 goto error;
3864 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003865 }
3866
Radek Krejcie534c132016-11-23 13:32:31 +01003867 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3868 if (strcmp(sub->ns->value, LY_NSYIN)) {
3869 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003870 ret = lyp_yin_fill_ext(retval, LYEXT_PAR_NODE, 0, 0, module, sub, &retval->ext, retval->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003871 retval->ext_size++;
3872 if (ret) {
3873 goto error;
3874 }
3875 } else {
3876 ret = fill_yin_iffeature(retval, 0, sub, &choice->iffeature[choice->iffeature_size], unres);
3877 choice->iffeature_size++;
3878 if (ret) {
3879 goto error;
3880 }
3881 }
3882 }
3883
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003884 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02003885 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003886 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "default", "choice");
3887 LOGVAL(LYE_SPEC, LY_VLOG_LYS, retval, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003888 goto error;
3889 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003890
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003891 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02003892 if (dflt) {
3893 GETVAL(value, dflt, "value");
3894 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003895 goto error;
3896 }
Radek Krejci629cdef2016-06-06 15:06:36 +02003897 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003898 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003899
Michal Vasko508a50d2016-09-07 14:50:33 +02003900 /* check XPath dependencies */
3901 if (choice->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3902 goto error;
3903 }
3904
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003905 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003906
3907error:
3908
Radek Krejci629cdef2016-06-06 15:06:36 +02003909 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003910 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003911
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003912 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003913}
3914
Michal Vasko0d343d12015-08-24 14:57:36 +02003915/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003916static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003917read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
3918 int valid_config, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02003919{
Radek Krejci76512572015-08-04 09:47:08 +02003920 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02003921 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003922 struct lyxml_elem *sub, *next;
3923 const char *value;
3924 int r;
3925 int f_mand = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01003926 int c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01003927 void *reallocated;
Radek Krejci863c2852015-06-03 15:47:11 +02003928
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003929 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01003930 if (!anyxml) {
3931 LOGMEM;
3932 return NULL;
3933 }
Radek Krejcibf2abff2016-08-23 15:51:52 +02003934 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02003935 anyxml->prev = (struct lys_node *)anyxml;
3936 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02003937
Radek Krejci07d0fb92017-01-13 14:11:05 +01003938 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
3939 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003940 goto error;
3941 }
Radek Krejci863c2852015-06-03 15:47:11 +02003942
Radek Krejcia9544502015-08-14 08:24:29 +02003943 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003944
Radek Krejcic189a952016-07-11 15:27:07 +02003945 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003946 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003947 goto error;
3948 }
3949
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003950 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01003951 if (strcmp(sub->ns->value, LY_NSYIN)) {
3952 /* extension */
3953 c_ext++;
3954 } else if (!strcmp(sub->name, "mandatory")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003955 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003956 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003957 goto error;
3958 }
3959 /* just checking the flags in leaf is not sufficient, we would allow
3960 * multiple mandatory statements with the "false" value
3961 */
3962 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02003963
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003964 GETVAL(value, sub, "value");
3965 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003966 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003967 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003968 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003969 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003970 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003971 goto error;
3972 }
3973 /* else false is the default value, so we can ignore it */
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01003974
3975 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
3976 goto error;
3977 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003978 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003979 } else if (!strcmp(sub->name, "when")) {
3980 if (anyxml->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003981 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003982 goto error;
3983 }
3984
Radek Krejci5323b492017-01-16 15:40:11 +01003985 anyxml->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003986 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003987 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003988 goto error;
3989 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003990 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003991 } else if (!strcmp(sub->name, "must")) {
3992 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003993 } else if (!strcmp(sub->name, "if-feature")) {
3994 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02003995
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003996 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003997 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003998 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003999 }
4000 }
Radek Krejci863c2852015-06-03 15:47:11 +02004001
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004002 /* middle part - process nodes with cardinality of 0..n */
4003 if (c_must) {
4004 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004005 if (!anyxml->must) {
4006 LOGMEM;
4007 goto error;
4008 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004009 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004010 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004011 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
4012 if (!anyxml->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004013 LOGMEM;
4014 goto error;
4015 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004016 }
Radek Krejcie534c132016-11-23 13:32:31 +01004017 if (c_ext) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004018 /* some extensions may be already present from the substatements */
4019 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4020 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004021 LOGMEM;
4022 goto error;
4023 }
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004024 retval->ext = reallocated;
4025
4026 /* init memory */
4027 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004028 }
Radek Krejci863c2852015-06-03 15:47:11 +02004029
Radek Krejcie534c132016-11-23 13:32:31 +01004030 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4031 if (strcmp(sub->ns->value, LY_NSYIN)) {
4032 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004033 r = lyp_yin_fill_ext(retval, LYEXT_PAR_NODE, 0, 0, module, sub, &retval->ext, retval->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01004034 retval->ext_size++;
4035 if (r) {
4036 goto error;
4037 }
4038 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004039 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004040 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004041 if (r) {
4042 goto error;
4043 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004044 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004045 r = fill_yin_iffeature(retval, 0, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004046 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004047 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004048 goto error;
4049 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004050 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004051 }
Radek Krejci863c2852015-06-03 15:47:11 +02004052
Michal Vasko508a50d2016-09-07 14:50:33 +02004053 /* check XPath dependencies */
4054 if ((anyxml->when || anyxml->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4055 goto error;
4056 }
4057
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004058 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02004059
4060error:
4061
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004062 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02004063
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004064 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02004065}
4066
Michal Vasko0d343d12015-08-24 14:57:36 +02004067/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004068static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004069read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004070 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004071{
Radek Krejci76512572015-08-04 09:47:08 +02004072 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004073 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004074 struct lyxml_elem *sub, *next;
4075 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01004076 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004077 int c_must = 0, c_ftrs = 0, f_mand = 0, c_ext = 0;
Radek Krejcifccd1442017-01-16 10:26:57 +01004078 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004079
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004080 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01004081 if (!leaf) {
4082 LOGMEM;
4083 return NULL;
4084 }
Radek Krejci76512572015-08-04 09:47:08 +02004085 leaf->nodetype = LYS_LEAF;
4086 leaf->prev = (struct lys_node *)leaf;
4087 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004088
Radek Krejci07d0fb92017-01-13 14:11:05 +01004089 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4090 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004091 goto error;
4092 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004093
Radek Krejcia9544502015-08-14 08:24:29 +02004094 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004095
Radek Krejcic189a952016-07-11 15:27:07 +02004096 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004097 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004098 goto error;
4099 }
4100
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004101 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004102 if (strcmp(sub->ns->value, LY_NSYIN)) {
4103 /* extension */
4104 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004105 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004106 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004107 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004108 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004109 goto error;
4110 }
Michal Vasko88c29542015-11-27 14:57:53 +01004111 /* HACK for unres */
4112 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004113 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004114 /* postpone type resolution when if-feature parsing is done since we need
4115 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004116 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004117 } else if (!strcmp(sub->name, "default")) {
4118 if (leaf->dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004119 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004120 goto error;
4121 }
4122 GETVAL(value, sub, "value");
4123 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci1abcdae2017-01-18 14:14:18 +01004124
4125 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
4126 goto error;
4127 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004128 } else if (!strcmp(sub->name, "units")) {
4129 if (leaf->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004130 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004131 goto error;
4132 }
4133 GETVAL(value, sub, "name");
4134 leaf->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004135
Radek Krejciac00b2a2017-01-17 14:05:00 +01004136 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004137 goto error;
4138 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004139 } else if (!strcmp(sub->name, "mandatory")) {
4140 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004141 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004142 goto error;
4143 }
4144 /* just checking the flags in leaf is not sufficient, we would allow
4145 * multiple mandatory statements with the "false" value
4146 */
4147 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02004148
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004149 GETVAL(value, sub, "value");
4150 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004151 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004152 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004153 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004154 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004155 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004156 goto error;
4157 } /* else false is the default value, so we can ignore it */
Radek Krejcifccd1442017-01-16 10:26:57 +01004158
Radek Krejciac00b2a2017-01-17 14:05:00 +01004159 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004160 goto error;
4161 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004162 } else if (!strcmp(sub->name, "when")) {
4163 if (leaf->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004164 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004165 goto error;
4166 }
4167
Radek Krejci5323b492017-01-16 15:40:11 +01004168 leaf->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004169 if (!leaf->when) {
4170 goto error;
4171 }
4172
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004173 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02004174 c_must++;
4175 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004176 } else if (!strcmp(sub->name, "if-feature")) {
4177 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004178 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004180 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004181 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004182 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004183 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004184
Michal Vasko88c29542015-11-27 14:57:53 +01004185 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004186 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004187
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004188 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004189 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004190 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004191 goto error;
4192 }
Michal Vasko478c4652016-07-21 12:55:01 +02004193 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004194 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "mandatory", "leaf");
4195 LOGVAL(LYE_SPEC, LY_VLOG_LYS, retval,
Michal Vasko478c4652016-07-21 12:55:01 +02004196 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
4197 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004198 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004199
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004200 /* middle part - process nodes with cardinality of 0..n */
4201 if (c_must) {
4202 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004203 if (!leaf->must) {
4204 LOGMEM;
4205 goto error;
4206 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004207 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004208 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004209 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
4210 if (!leaf->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004211 LOGMEM;
4212 goto error;
4213 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004214 }
Radek Krejcie534c132016-11-23 13:32:31 +01004215 if (c_ext) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004216 /* some extensions may be already present from the substatements */
4217 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4218 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004219 LOGMEM;
4220 goto error;
4221 }
Radek Krejcifccd1442017-01-16 10:26:57 +01004222 retval->ext = reallocated;
4223
4224 /* init memory */
4225 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004226 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004227
Radek Krejcie534c132016-11-23 13:32:31 +01004228 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4229 if (strcmp(sub->ns->value, LY_NSYIN)) {
4230 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004231 r = lyp_yin_fill_ext(retval, LYEXT_PAR_NODE, 0, 0, module, sub, &retval->ext, retval->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01004232 retval->ext_size++;
4233 if (r) {
4234 goto error;
4235 }
4236 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004237 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004238 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004239 if (r) {
4240 goto error;
4241 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004242 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004243 r = fill_yin_iffeature(retval, 0, sub, &leaf->iffeature[leaf->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004244 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004245 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004246 goto error;
4247 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004248 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004249 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004250
Radek Krejcicbb473e2016-09-16 14:48:32 +02004251 /* finalize type parsing */
4252 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
4253 leaf->type.der = NULL;
4254 goto error;
4255 }
4256
4257 /* check default value (if not defined, there still could be some restrictions
4258 * that need to be checked against a default value from a derived type) */
Radek Krejci51673202016-11-01 17:00:32 +01004259 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt)) == -1) {
Radek Krejcicbb473e2016-09-16 14:48:32 +02004260 goto error;
4261 }
4262
Michal Vasko508a50d2016-09-07 14:50:33 +02004263 /* check XPath dependencies */
4264 if ((leaf->when || leaf->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4265 goto error;
4266 }
4267
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004268 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004269
4270error:
4271
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004272 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004273
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004274 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004275}
4276
Michal Vasko0d343d12015-08-24 14:57:36 +02004277/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004278static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004279read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004280 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004281{
Radek Krejci76512572015-08-04 09:47:08 +02004282 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004283 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004284 struct lyxml_elem *sub, *next;
4285 const char *value;
4286 char *endptr;
4287 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004288 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004289 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004290 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejci5323b492017-01-16 15:40:11 +01004291 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004292
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004293 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01004294 if (!llist) {
4295 LOGMEM;
4296 return NULL;
4297 }
Radek Krejci76512572015-08-04 09:47:08 +02004298 llist->nodetype = LYS_LEAFLIST;
4299 llist->prev = (struct lys_node *)llist;
4300 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004301
Radek Krejci07d0fb92017-01-13 14:11:05 +01004302 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4303 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004304 goto error;
4305 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004306
Radek Krejcia9544502015-08-14 08:24:29 +02004307 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004308
Radek Krejcic189a952016-07-11 15:27:07 +02004309 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004310 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004311 goto error;
4312 }
4313
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004314 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004315 if (strcmp(sub->ns->value, LY_NSYIN)) {
4316 /* extension */
4317 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004318 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004319 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004320 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004321 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004322 goto error;
4323 }
Michal Vasko88c29542015-11-27 14:57:53 +01004324 /* HACK for unres */
4325 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004326 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004327 /* postpone type resolution when if-feature parsing is done since we need
4328 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004329 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004330 } else if (!strcmp(sub->name, "units")) {
4331 if (llist->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004332 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004333 goto error;
4334 }
4335 GETVAL(value, sub, "name");
4336 llist->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004337
Radek Krejciac00b2a2017-01-17 14:05:00 +01004338 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004339 goto error;
4340 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004341 } else if (!strcmp(sub->name, "ordered-by")) {
4342 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004343 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004344 goto error;
4345 }
4346 /* just checking the flags in llist is not sufficient, we would
4347 * allow multiple ordered-by statements with the "system" value
4348 */
4349 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004350
Radek Krejci1574a8d2015-08-03 14:16:52 +02004351 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004352 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4353 * state data
4354 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004355 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004356 continue;
4357 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004358
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004359 GETVAL(value, sub, "value");
4360 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004361 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004362 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004363 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004364 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02004365 } /* else system is the default value, so we can ignore it */
4366
Radek Krejciac00b2a2017-01-17 14:05:00 +01004367 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
4368 goto error;
4369 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004370 } else if (!strcmp(sub->name, "must")) {
4371 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02004372 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004373 } else if (!strcmp(sub->name, "if-feature")) {
4374 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004375 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02004376 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004377 /* read the default's extension instances */
4378 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, c_dflt, unres)) {
4379 goto error;
4380 }
4381
Radek Krejcid5a5c282016-08-15 15:38:08 +02004382 c_dflt++;
4383 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004384
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004385 } else if (!strcmp(sub->name, "min-elements")) {
4386 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004387 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004388 goto error;
4389 }
4390 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004391
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004392 GETVAL(value, sub, "value");
4393 while (isspace(value[0])) {
4394 value++;
4395 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004396
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004397 /* convert it to uint32_t */
4398 errno = 0;
4399 endptr = NULL;
4400 val = strtoul(value, &endptr, 10);
4401 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004402 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004403 goto error;
4404 }
4405 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004406 if (llist->max && (llist->min > llist->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004407 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
4408 LOGVAL(LYE_SPEC, LY_VLOG_LYS, retval, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004409 goto error;
4410 }
Radek Krejci5323b492017-01-16 15:40:11 +01004411
Radek Krejciac00b2a2017-01-17 14:05:00 +01004412 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004413 goto error;
4414 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004415 } else if (!strcmp(sub->name, "max-elements")) {
4416 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004417 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004418 goto error;
4419 }
4420 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004421
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004422 GETVAL(value, sub, "value");
4423 while (isspace(value[0])) {
4424 value++;
4425 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004426
Radek Krejci0d7b2472016-02-12 11:11:03 +01004427 if (!strcmp(value, "unbounded")) {
4428 llist->max = 0;
4429 } else {
4430 /* convert it to uint32_t */
4431 errno = 0;
4432 endptr = NULL;
4433 val = strtoul(value, &endptr, 10);
4434 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004435 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004436 goto error;
4437 }
4438 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004439 if (llist->min > llist->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004440 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
4441 LOGVAL(LYE_SPEC, LY_VLOG_LYS, retval, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004442 goto error;
4443 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004444 }
Radek Krejci5323b492017-01-16 15:40:11 +01004445
Radek Krejciac00b2a2017-01-17 14:05:00 +01004446 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004447 goto error;
4448 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004449 } else if (!strcmp(sub->name, "when")) {
4450 if (llist->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004451 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004452 goto error;
4453 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004454
Radek Krejci5323b492017-01-16 15:40:11 +01004455 llist->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004456 if (!llist->when) {
4457 goto error;
4458 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004459 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004460 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004461 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004462 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004463
Michal Vasko88c29542015-11-27 14:57:53 +01004464 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004465 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004466
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004467 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004468 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004469 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004470 goto error;
4471 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004472
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004473 /* middle part - process nodes with cardinality of 0..n */
4474 if (c_must) {
4475 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004476 if (!llist->must) {
4477 LOGMEM;
4478 goto error;
4479 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004480 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004481 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004482 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
4483 if (!llist->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004484 LOGMEM;
4485 goto error;
4486 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004487 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004488 if (c_dflt) {
4489 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
4490 if (!llist->dflt) {
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004491 LOGMEM;
4492 goto error;
4493 }
4494 }
Radek Krejcie534c132016-11-23 13:32:31 +01004495 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01004496 /* some extensions may be already present from the substatements */
4497 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4498 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004499 LOGMEM;
4500 goto error;
4501 }
Radek Krejci5323b492017-01-16 15:40:11 +01004502 retval->ext = reallocated;
4503
4504 /* init memory */
4505 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004506 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004507
Radek Krejcie534c132016-11-23 13:32:31 +01004508 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4509 if (strcmp(sub->ns->value, LY_NSYIN)) {
4510 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004511 r = lyp_yin_fill_ext(retval, LYEXT_PAR_NODE, 0, 0, module, sub, &retval->ext, retval->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01004512 retval->ext_size++;
4513 if (r) {
4514 goto error;
4515 }
4516 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004517 r = fill_yin_must(module, sub, &llist->must[llist->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004518 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004519 if (r) {
4520 goto error;
4521 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004522 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004523 r = fill_yin_iffeature(retval, 0, sub, &llist->iffeature[llist->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004524 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004525 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004526 goto error;
4527 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004528 } else if (!strcmp(sub->name, "default")) {
4529 GETVAL(value, sub, "value");
4530
Radek Krejciac1a52c2016-09-15 14:42:40 +02004531 /* check for duplicity in case of configuration data,
4532 * in case of status data duplicities are allowed */
4533 if (llist->flags & LYS_CONFIG_W) {
4534 for (r = 0; r < llist->dflt_size; r++) {
4535 if (ly_strequal(llist->dflt[r], value, 1)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004536 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, "default");
4537 LOGVAL(LYE_SPEC, LY_VLOG_LYS, retval, "Duplicated default value \"%s\".", value);
Radek Krejciac1a52c2016-09-15 14:42:40 +02004538 goto error;
4539 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004540 }
4541 }
4542 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004543 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004544 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004545
Radek Krejcicbb473e2016-09-16 14:48:32 +02004546 /* finalize type parsing */
4547 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
4548 llist->type.der = NULL;
4549 goto error;
4550 }
4551
Radek Krejcid5a5c282016-08-15 15:38:08 +02004552 if (llist->dflt_size && llist->min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004553 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "min-elements", "leaf-list");
4554 LOGVAL(LYE_SPEC, LY_VLOG_LYS, retval,
Radek Krejcid5a5c282016-08-15 15:38:08 +02004555 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
4556 goto error;
4557 }
4558
4559 /* check default value (if not defined, there still could be some restrictions
4560 * that need to be checked against a default value from a derived type) */
4561 for (r = 0; r < llist->dflt_size; r++) {
Radek Krejci51673202016-11-01 17:00:32 +01004562 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
4563 (struct lys_node *)(&llist->dflt[r])) == -1) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02004564 goto error;
Radek Krejci25d782a2015-05-22 15:03:23 +02004565 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004566 }
4567
Michal Vasko508a50d2016-09-07 14:50:33 +02004568 /* check XPath dependencies */
4569 if ((llist->when || llist->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4570 goto error;
4571 }
4572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004573 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004574
4575error:
4576
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004577 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004578
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004579 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004580}
4581
Michal Vasko0d343d12015-08-24 14:57:36 +02004582/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004583static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004584read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004585 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004586{
Radek Krejci1d82ef62015-08-07 14:44:40 +02004587 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02004588 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004589 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01004590 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01004591 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004592 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejci5c08a992016-11-02 13:30:04 +01004593 const char *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004594 char *auxs;
4595 unsigned long val;
Radek Krejcie36d7c72017-01-17 16:12:30 +01004596 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004597
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004598 /* init */
4599 memset(&root, 0, sizeof root);
4600 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02004601
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004602 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01004603 if (!list) {
4604 LOGMEM;
4605 return NULL;
4606 }
Radek Krejci76512572015-08-04 09:47:08 +02004607 list->nodetype = LYS_LIST;
4608 list->prev = (struct lys_node *)list;
4609 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004610
Radek Krejci07d0fb92017-01-13 14:11:05 +01004611 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4612 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004613 goto error;
4614 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004615
Radek Krejcia9544502015-08-14 08:24:29 +02004616 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4617
Radek Krejcic189a952016-07-11 15:27:07 +02004618 /* insert the node into the schema tree */
4619 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4620 goto error;
4621 }
4622
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004623 /* process list's specific children */
4624 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004625 if (strcmp(sub->ns->value, LY_NSYIN)) {
4626 /* extension */
4627 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004628 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02004629
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004630 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01004631 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004632 !strcmp(sub->name, "leaf-list") ||
4633 !strcmp(sub->name, "leaf") ||
4634 !strcmp(sub->name, "list") ||
4635 !strcmp(sub->name, "choice") ||
4636 !strcmp(sub->name, "uses") ||
4637 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004638 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02004639 !strcmp(sub->name, "action") ||
4640 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004641 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004642 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004643
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004644 /* array counters */
4645 } else if (!strcmp(sub->name, "key")) {
4646 /* check cardinality 0..1 */
4647 if (list->keys_size) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004648 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004649 goto error;
4650 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004651
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004652 /* count the number of keys */
4653 GETVAL(value, sub, "value");
Radek Krejci5c08a992016-11-02 13:30:04 +01004654 list->keys_str = lydict_insert(module->ctx, value, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004655 while ((value = strpbrk(value, " \t\n"))) {
4656 list->keys_size++;
4657 while (isspace(*value)) {
4658 value++;
4659 }
4660 }
4661 list->keys_size++;
4662 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01004663 if (!list->keys) {
4664 LOGMEM;
4665 goto error;
4666 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01004667
4668 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_KEY, 0, unres)) {
4669 goto error;
4670 }
4671 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004672 } else if (!strcmp(sub->name, "unique")) {
4673 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02004674 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004675 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004676 } else if (!strcmp(sub->name, "typedef")) {
4677 c_tpdf++;
4678 } else if (!strcmp(sub->name, "must")) {
4679 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004680 } else if (!strcmp(sub->name, "if-feature")) {
4681 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02004682
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004683 /* optional stetments */
4684 } else if (!strcmp(sub->name, "ordered-by")) {
4685 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004686 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004687 goto error;
4688 }
4689 /* just checking the flags in llist is not sufficient, we would
4690 * allow multiple ordered-by statements with the "system" value
4691 */
4692 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004693
Radek Krejci1574a8d2015-08-03 14:16:52 +02004694 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004695 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4696 * state data
4697 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004698 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004699 continue;
4700 }
Radek Krejci345ad742015-06-03 11:04:18 +02004701
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004702 GETVAL(value, sub, "value");
4703 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004704 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004705 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004706 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004707 goto error;
Radek Krejcie36d7c72017-01-17 16:12:30 +01004708 } /* else system is the default value, so we can ignore it */
4709
4710 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
4711 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004712 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004713 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004714 } else if (!strcmp(sub->name, "min-elements")) {
4715 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004716 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004717 goto error;
4718 }
4719 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004720
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004721 GETVAL(value, sub, "value");
4722 while (isspace(value[0])) {
4723 value++;
4724 }
Radek Krejci345ad742015-06-03 11:04:18 +02004725
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004726 /* convert it to uint32_t */
4727 errno = 0;
4728 auxs = NULL;
4729 val = strtoul(value, &auxs, 10);
4730 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004731 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004732 goto error;
4733 }
4734 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004735 if (list->max && (list->min > list->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004736 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
4737 LOGVAL(LYE_SPEC, LY_VLOG_LYS, retval, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004738 lyxml_free(module->ctx, sub);
4739 goto error;
4740 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01004741 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
4742 goto error;
4743 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004744 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004745 } else if (!strcmp(sub->name, "max-elements")) {
4746 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004747 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004748 goto error;
4749 }
4750 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004751
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004752 GETVAL(value, sub, "value");
4753 while (isspace(value[0])) {
4754 value++;
4755 }
Radek Krejci345ad742015-06-03 11:04:18 +02004756
Radek Krejci0d7b2472016-02-12 11:11:03 +01004757 if (!strcmp(value, "unbounded")) {
4758 list->max = 0;;
4759 } else {
4760 /* convert it to uint32_t */
4761 errno = 0;
4762 auxs = NULL;
4763 val = strtoul(value, &auxs, 10);
4764 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004765 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004766 goto error;
4767 }
4768 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004769 if (list->min > list->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004770 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
4771 LOGVAL(LYE_SPEC, LY_VLOG_LYS, retval, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004772 goto error;
4773 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004774 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01004775 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
4776 goto error;
4777 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004778 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004779 } else if (!strcmp(sub->name, "when")) {
4780 if (list->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004781 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004782 goto error;
4783 }
4784
Radek Krejci5323b492017-01-16 15:40:11 +01004785 list->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004786 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004787 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004788 goto error;
4789 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004790 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004791 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004792 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004793 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004794 }
4795 }
Radek Krejci345ad742015-06-03 11:04:18 +02004796
Michal Vaskoe022a562016-09-27 14:24:15 +02004797 /* check - if list is configuration, key statement is mandatory
4798 * (but only if we are not in a grouping or augment, then the check is deferred) */
4799 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT)); node = node->parent);
Radek Krejci5c08a992016-11-02 13:30:04 +01004800 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys_str) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004801 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004802 goto error;
4803 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004804
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004805 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4806 if (c_tpdf) {
4807 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004808 if (!list->tpdf) {
4809 LOGMEM;
4810 goto error;
4811 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004812 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004813 if (c_must) {
4814 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004815 if (!list->must) {
4816 LOGMEM;
4817 goto error;
4818 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004819 }
4820 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004821 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
4822 if (!list->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004823 LOGMEM;
4824 goto error;
4825 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004826 }
Radek Krejcie534c132016-11-23 13:32:31 +01004827 if (c_ext) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01004828 /* some extensions may be already present from the substatements */
4829 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4830 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004831 LOGMEM;
4832 goto error;
4833 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01004834 retval->ext = reallocated;
4835
4836 /* init memory */
4837 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004838 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01004839
Radek Krejcie534c132016-11-23 13:32:31 +01004840 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4841 if (strcmp(sub->ns->value, LY_NSYIN)) {
4842 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004843 r = lyp_yin_fill_ext(retval, LYEXT_PAR_NODE, 0, 0, module, sub, &retval->ext, retval->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01004844 retval->ext_size++;
4845 if (r) {
4846 goto error;
4847 }
4848 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004849 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
4850 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004851 if (r) {
4852 goto error;
4853 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004854 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004855 r = fill_yin_iffeature(retval, 0, sub, &list->iffeature[list->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004856 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004857 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004858 goto error;
4859 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004860 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004861 r = fill_yin_must(module, sub, &list->must[list->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004862 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004863 if (r) {
4864 goto error;
4865 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004866 }
4867 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004868
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004869 /* last part - process data nodes */
4870 LY_TREE_FOR_SAFE(root.child, next, sub) {
4871 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004872 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004873 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004874 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004875 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004876 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004877 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004878 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004879 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004880 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004881 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004882 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004883 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004884 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004885 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004886 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004887 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004888 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004889 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004890 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02004891 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004892 node = read_yin_notif(module, retval, sub, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02004893 } else {
4894 LOGINT;
4895 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004896 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004897 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004898 goto error;
4899 }
Radek Krejci73adb602015-07-02 18:07:40 +02004900
Michal Vasko345da0a2015-12-02 10:35:55 +01004901 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004902 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004903
Radek Krejci5c08a992016-11-02 13:30:04 +01004904 if (list->keys_str) {
4905 /* check that we are not in grouping */
4906 for (node = parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
4907 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01004908 goto error;
4909 }
4910 } /* else config false list without a key, key_str presence in case of config true is checked earlier */
Radek Krejci812b10a2015-05-28 16:48:25 +02004911
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004912 /* process unique statements */
4913 if (c_uniq) {
4914 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01004915 if (!list->unique) {
4916 LOGMEM;
4917 goto error;
4918 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02004919
Radek Krejci461efb92016-02-12 15:52:18 +01004920 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
4921 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
4922 list->unique_size++;
4923 if (r) {
4924 goto error;
4925 }
4926
Radek Krejcie36d7c72017-01-17 16:12:30 +01004927 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub,
4928 LYEXT_SUBSTMT_UNIQUE, list->unique_size - 1, unres)) {
4929 goto error;
4930 }
Radek Krejci461efb92016-02-12 15:52:18 +01004931 lyxml_free(module->ctx, sub);
4932 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004933 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02004934
Michal Vasko508a50d2016-09-07 14:50:33 +02004935 /* check XPath dependencies */
4936 if ((list->when || list->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4937 goto error;
4938 }
4939
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004940 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004941
4942error:
4943
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004944 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004945 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004946 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004947 }
4948 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004949 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004950 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004951
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004952 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004953}
4954
Michal Vasko0d343d12015-08-24 14:57:36 +02004955/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004956static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004957read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004958 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004959{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004960 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004961 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004962 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004963 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004964 const char *value;
Radek Krejci07d0fb92017-01-13 14:11:05 +01004965 void *reallocated;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004966 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01004967 int c_tpdf = 0, c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004968
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004969 /* init */
4970 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02004971
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004972 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01004973 if (!cont) {
4974 LOGMEM;
4975 return NULL;
4976 }
Radek Krejci76512572015-08-04 09:47:08 +02004977 cont->nodetype = LYS_CONTAINER;
4978 cont->prev = (struct lys_node *)cont;
4979 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004980
Radek Krejci07d0fb92017-01-13 14:11:05 +01004981 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4982 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004983 goto error;
4984 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004985
Radek Krejcia9544502015-08-14 08:24:29 +02004986 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4987
Radek Krejcic189a952016-07-11 15:27:07 +02004988 /* insert the node into the schema tree */
4989 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4990 goto error;
4991 }
4992
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004993 /* process container's specific children */
4994 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004995 if (strcmp(sub->ns->value, LY_NSYIN)) {
4996 /* extension */
4997 c_ext++;
4998 } else if (!strcmp(sub->name, "presence")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004999 if (cont->presence) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005000 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005001 goto error;
5002 }
5003 GETVAL(value, sub, "value");
5004 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02005005
Radek Krejciac00b2a2017-01-17 14:05:00 +01005006 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005007 goto error;
5008 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005009 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005010 } else if (!strcmp(sub->name, "when")) {
5011 if (cont->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005012 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005013 goto error;
5014 }
5015
Radek Krejci5323b492017-01-16 15:40:11 +01005016 cont->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005017 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005018 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005019 goto error;
5020 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005021 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02005022
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005023 /* data statements */
5024 } else if (!strcmp(sub->name, "container") ||
5025 !strcmp(sub->name, "leaf-list") ||
5026 !strcmp(sub->name, "leaf") ||
5027 !strcmp(sub->name, "list") ||
5028 !strcmp(sub->name, "choice") ||
5029 !strcmp(sub->name, "uses") ||
5030 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005031 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005032 !strcmp(sub->name, "action") ||
5033 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005034 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005035 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005036
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005037 /* array counters */
5038 } else if (!strcmp(sub->name, "typedef")) {
5039 c_tpdf++;
5040 } else if (!strcmp(sub->name, "must")) {
5041 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005042 } else if (!strcmp(sub->name, "if-feature")) {
5043 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005044 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005045 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005046 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005047 }
5048 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005049
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005050 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5051 if (c_tpdf) {
5052 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005053 if (!cont->tpdf) {
5054 LOGMEM;
5055 goto error;
5056 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005057 }
5058 if (c_must) {
5059 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01005060 if (!cont->must) {
5061 LOGMEM;
5062 goto error;
5063 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005064 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005065 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005066 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
5067 if (!cont->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005068 LOGMEM;
5069 goto error;
5070 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005071 }
Radek Krejcie534c132016-11-23 13:32:31 +01005072 if (c_ext) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01005073 /* some extensions may be already present from the substatements */
5074 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5075 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005076 LOGMEM;
5077 goto error;
5078 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01005079 retval->ext = reallocated;
5080
5081 /* init memory */
5082 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005083 }
Radek Krejci800af702015-06-02 13:46:01 +02005084
Radek Krejcie534c132016-11-23 13:32:31 +01005085 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5086 if (strcmp(sub->ns->value, LY_NSYIN)) {
5087 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005088 r = lyp_yin_fill_ext(retval, LYEXT_PAR_NODE, 0, 0, module, sub, &retval->ext, retval->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01005089 retval->ext_size++;
5090 if (r) {
5091 goto error;
5092 }
5093 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005094 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
5095 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005096 if (r) {
5097 goto error;
5098 }
5099 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005100 r = fill_yin_must(module, sub, &cont->must[cont->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005101 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005102 if (r) {
5103 goto error;
5104 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005105 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005106 r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005107 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005108 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005109 goto error;
5110 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005111 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005112 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005113
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005114 /* last part - process data nodes */
5115 LY_TREE_FOR_SAFE(root.child, next, sub) {
5116 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005117 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005118 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005119 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005120 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005121 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005122 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005123 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005124 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005125 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005126 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005127 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005128 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005129 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005130 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005131 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005132 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005133 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005134 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005135 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005136 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005137 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005138 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005139 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005140 goto error;
5141 }
Radek Krejci73adb602015-07-02 18:07:40 +02005142
Michal Vasko345da0a2015-12-02 10:35:55 +01005143 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005144 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005145
Michal Vasko508a50d2016-09-07 14:50:33 +02005146 /* check XPath dependencies */
5147 if ((cont->when || cont->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5148 goto error;
5149 }
5150
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005151 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005152
5153error:
5154
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005155 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005156 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005157 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005158 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005159
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005160 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005161}
5162
Michal Vasko0d343d12015-08-24 14:57:36 +02005163/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005164static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005165read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02005166 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005167{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005168 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005169 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005170 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005171 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005172 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005173 int c_tpdf = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005174
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005175 /* init */
5176 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005177
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005178 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01005179 if (!grp) {
5180 LOGMEM;
5181 return NULL;
5182 }
Radek Krejci76512572015-08-04 09:47:08 +02005183 grp->nodetype = LYS_GROUPING;
5184 grp->prev = (struct lys_node *)grp;
5185 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005186
Radek Krejci07d0fb92017-01-13 14:11:05 +01005187 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE , unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005188 goto error;
5189 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005190
Radek Krejcia9544502015-08-14 08:24:29 +02005191 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5192
Radek Krejcic189a952016-07-11 15:27:07 +02005193 /* insert the node into the schema tree */
5194 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5195 goto error;
5196 }
5197
Radek Krejci1d82ef62015-08-07 14:44:40 +02005198 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005199 if (strcmp(sub->ns->value, LY_NSYIN)) {
5200 /* extension */
5201 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005202
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005203 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005204 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005205 !strcmp(sub->name, "leaf-list") ||
5206 !strcmp(sub->name, "leaf") ||
5207 !strcmp(sub->name, "list") ||
5208 !strcmp(sub->name, "choice") ||
5209 !strcmp(sub->name, "uses") ||
5210 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005211 !strcmp(sub->name, "anyxml") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02005212 !strcmp(sub->name, "action") ||
5213 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005214 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005215 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005216
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005217 /* array counters */
5218 } else if (!strcmp(sub->name, "typedef")) {
5219 c_tpdf++;
5220 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005221 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005222 goto error;
5223 }
5224 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005225
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005226 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5227 if (c_tpdf) {
5228 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005229 if (!grp->tpdf) {
5230 LOGMEM;
5231 goto error;
5232 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005233 }
Radek Krejcie534c132016-11-23 13:32:31 +01005234 if (c_ext) {
5235 grp->ext = calloc(c_ext, sizeof *grp->ext);
5236 if (!grp->ext) {
5237 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02005238 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005239 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005240 }
Radek Krejcie534c132016-11-23 13:32:31 +01005241 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5242 if (strcmp(sub->ns->value, LY_NSYIN)) {
5243 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005244 r = lyp_yin_fill_ext(retval, LYEXT_PAR_NODE, 0, 0, module, sub, &retval->ext, retval->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01005245 retval->ext_size++;
5246 if (r) {
5247 goto error;
5248 }
5249 } else {
5250 /* typedef */
5251 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
5252 grp->tpdf_size++;
5253 if (r) {
5254 goto error;
5255 }
5256 }
5257 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005258
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005259 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02005260 if (!root.child) {
5261 LOGWRN("Grouping \"%s\" without children.", retval->name);
5262 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005263 LY_TREE_FOR_SAFE(root.child, next, sub) {
5264 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005265 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005266 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005267 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005268 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005269 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005270 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005271 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005272 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005273 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005274 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005275 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005276 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005277 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005278 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005279 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005280 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005281 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005282 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005283 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02005284 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005285 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005286 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005287 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005288 goto error;
5289 }
Radek Krejci73adb602015-07-02 18:07:40 +02005290
Michal Vasko345da0a2015-12-02 10:35:55 +01005291 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005292 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005293
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005294 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005295
5296error:
5297
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005298 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005299 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005300 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005301 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005302
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005303 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005304}
5305
Michal Vasko0d343d12015-08-24 14:57:36 +02005306/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005307static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005308read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02005309 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005310{
Radek Krejcie0674f82015-06-15 13:58:51 +02005311 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005312 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02005313 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02005314 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005315 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005316 int c_tpdf = 0, c_must = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005317
Radek Krejcie0674f82015-06-15 13:58:51 +02005318 /* init */
5319 memset(&root, 0, sizeof root);
5320
Michal Vasko38d01f72015-06-15 09:41:06 +02005321 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01005322 if (!inout) {
5323 LOGMEM;
5324 return NULL;
5325 }
Radek Krejci6acc8012015-08-13 09:07:04 +02005326 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005327
5328 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02005329 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005330 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005331 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02005332 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005333 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005334 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02005335 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02005336 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02005337 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005338 }
5339
Radek Krejci76512572015-08-04 09:47:08 +02005340 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005341
Radek Krejci07d0fb92017-01-13 14:11:05 +01005342 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02005343 goto error;
5344 }
5345
Radek Krejcia9544502015-08-14 08:24:29 +02005346 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5347
Radek Krejcic189a952016-07-11 15:27:07 +02005348 /* insert the node into the schema tree */
5349 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5350 goto error;
5351 }
5352
Michal Vasko38d01f72015-06-15 09:41:06 +02005353 /* data statements */
5354 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005355 if (strcmp(sub->ns->value, LY_NSYIN)) {
5356 /* extension */
5357 c_ext++;
5358 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005359 !strcmp(sub->name, "leaf-list") ||
5360 !strcmp(sub->name, "leaf") ||
5361 !strcmp(sub->name, "list") ||
5362 !strcmp(sub->name, "choice") ||
5363 !strcmp(sub->name, "uses") ||
5364 !strcmp(sub->name, "grouping") ||
5365 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005366 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005367 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005368
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005369 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005370 } else if (!strcmp(sub->name, "typedef")) {
5371 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02005372
Radek Krejci1a31efe2016-07-29 11:04:16 +02005373 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005374 c_must++;
5375
Michal Vasko38d01f72015-06-15 09:41:06 +02005376 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005377 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005378 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005379 }
5380 }
5381
5382 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5383 if (c_tpdf) {
5384 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005385 if (!inout->tpdf) {
5386 LOGMEM;
5387 goto error;
5388 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005389 }
Radek Krejci19332802016-07-29 10:39:46 +02005390 if (c_must) {
5391 inout->must = calloc(c_must, sizeof *inout->must);
5392 if (!inout->must) {
5393 LOGMEM;
5394 goto error;
5395 }
5396 }
Radek Krejcie534c132016-11-23 13:32:31 +01005397 if (c_ext) {
5398 inout->ext = calloc(c_ext, sizeof *inout->ext);
5399 if (!inout->ext) {
5400 LOGMEM;
5401 goto error;
5402 }
5403 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005404
Radek Krejcie534c132016-11-23 13:32:31 +01005405 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5406 if (strcmp(sub->ns->value, LY_NSYIN)) {
5407 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005408 r = lyp_yin_fill_ext(retval, LYEXT_PAR_NODE, 0, 0, module, sub, &retval->ext, retval->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01005409 retval->ext_size++;
5410 if (r) {
5411 goto error;
5412 }
5413 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005414 r = fill_yin_must(module, sub, &inout->must[inout->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02005415 inout->must_size++;
5416 if (r) {
5417 goto error;
5418 }
5419 } else { /* typedef */
5420 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
5421 inout->tpdf_size++;
5422 if (r) {
5423 goto error;
5424 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005425 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005426 }
5427
5428 /* last part - process data nodes */
5429 LY_TREE_FOR_SAFE(root.child, next, sub) {
5430 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005431 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005432 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005433 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005434 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005435 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005436 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005437 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005438 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005439 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005440 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005441 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005442 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005443 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005444 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005445 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005446 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005447 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005448 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005449 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005450 goto error;
5451 }
Radek Krejci73adb602015-07-02 18:07:40 +02005452
Michal Vasko345da0a2015-12-02 10:35:55 +01005453 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005454 }
5455
Michal Vasko508a50d2016-09-07 14:50:33 +02005456 /* check XPath dependencies */
5457 if (inout->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5458 goto error;
5459 }
5460
Michal Vasko38d01f72015-06-15 09:41:06 +02005461 return retval;
5462
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005463error:
Michal Vasko38d01f72015-06-15 09:41:06 +02005464
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005465 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02005466 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005467 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005468 }
5469
5470 return NULL;
5471}
5472
Michal Vasko0d343d12015-08-24 14:57:36 +02005473/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005474static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005475read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02005476 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02005477{
Michal Vaskoc6551b32015-06-16 10:51:43 +02005478 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005479 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005480 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005481 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005482 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005483 int c_tpdf = 0, c_ftrs = 0, c_must = 0, c_ext = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02005484
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005485 if (parent && (module->version < 2)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005486 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "notification");
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005487 return NULL;
5488 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005489
Michal Vaskoc6551b32015-06-16 10:51:43 +02005490 memset(&root, 0, sizeof root);
5491
Michal Vasko0ea41032015-06-16 08:53:55 +02005492 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01005493 if (!notif) {
5494 LOGMEM;
5495 return NULL;
5496 }
Radek Krejci76512572015-08-04 09:47:08 +02005497 notif->nodetype = LYS_NOTIF;
5498 notif->prev = (struct lys_node *)notif;
5499 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005500
Radek Krejci07d0fb92017-01-13 14:11:05 +01005501 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005502 goto error;
5503 }
5504
Radek Krejcia9544502015-08-14 08:24:29 +02005505 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5506
Radek Krejcic189a952016-07-11 15:27:07 +02005507 /* insert the node into the schema tree */
5508 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5509 goto error;
5510 }
5511
Michal Vasko0ea41032015-06-16 08:53:55 +02005512 /* process rpc's specific children */
5513 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005514 if (strcmp(sub->ns->value, LY_NSYIN)) {
5515 /* extension */
5516 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005517 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02005518
Michal Vasko0ea41032015-06-16 08:53:55 +02005519 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005520 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005521 !strcmp(sub->name, "leaf-list") ||
5522 !strcmp(sub->name, "leaf") ||
5523 !strcmp(sub->name, "list") ||
5524 !strcmp(sub->name, "choice") ||
5525 !strcmp(sub->name, "uses") ||
5526 !strcmp(sub->name, "grouping") ||
5527 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005528 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005529 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02005530
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005531 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02005532 } else if (!strcmp(sub->name, "typedef")) {
5533 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005534 } else if (!strcmp(sub->name, "if-feature")) {
5535 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02005536 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005537 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02005538 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005539 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02005540 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02005541 }
5542 }
5543
5544 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5545 if (c_tpdf) {
5546 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005547 if (!notif->tpdf) {
5548 LOGMEM;
5549 goto error;
5550 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005551 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005552 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005553 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
5554 if (!notif->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005555 LOGMEM;
5556 goto error;
5557 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005558 }
Radek Krejci19332802016-07-29 10:39:46 +02005559 if (c_must) {
5560 notif->must = calloc(c_must, sizeof *notif->must);
5561 if (!notif->must) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005562 LOGMEM;
5563 goto error;
5564 }
5565 }
Radek Krejcie534c132016-11-23 13:32:31 +01005566 if (c_ext) {
5567 notif->ext = calloc(c_ext, sizeof *notif->ext);
5568 if (!notif->ext) {
5569 LOGMEM;
5570 goto error;
5571 }
5572 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005573
Radek Krejcie534c132016-11-23 13:32:31 +01005574 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5575 if (strcmp(sub->ns->value, LY_NSYIN)) {
5576 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005577 r = lyp_yin_fill_ext(retval, LYEXT_PAR_NODE, 0, 0, module, sub, &retval->ext, retval->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01005578 retval->ext_size++;
5579 if (r) {
5580 goto error;
5581 }
5582 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005583 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
5584 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02005585 if (r) {
5586 goto error;
5587 }
Radek Krejci96299152016-06-22 10:17:50 +02005588 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005589 r = fill_yin_iffeature(retval, 0, sub, &notif->iffeature[notif->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005590 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005591 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005592 goto error;
5593 }
Radek Krejci19332802016-07-29 10:39:46 +02005594 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005595 r = fill_yin_must(module, sub, &notif->must[notif->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02005596 notif->must_size++;
Radek Krejci0b24d752015-07-02 15:02:27 +02005597 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005598 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005599 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005600 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005601 }
5602
5603 /* last part - process data nodes */
5604 LY_TREE_FOR_SAFE(root.child, next, sub) {
5605 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005606 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005607 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005608 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005609 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005610 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005611 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005612 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005613 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005614 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005615 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005616 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005617 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005618 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005619 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005620 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005621 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005622 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005623 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005624 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005625 goto error;
5626 }
Radek Krejci73adb602015-07-02 18:07:40 +02005627
Michal Vasko345da0a2015-12-02 10:35:55 +01005628 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02005629 }
5630
Michal Vasko508a50d2016-09-07 14:50:33 +02005631 /* check XPath dependencies */
5632 if (notif->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5633 goto error;
5634 }
5635
Michal Vasko0ea41032015-06-16 08:53:55 +02005636 return retval;
5637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005638error:
Michal Vasko0ea41032015-06-16 08:53:55 +02005639
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005640 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02005641 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005642 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02005643 }
5644
5645 return NULL;
5646}
5647
Michal Vasko0d343d12015-08-24 14:57:36 +02005648/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005649static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005650read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005651 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005652{
Radek Krejcie0674f82015-06-15 13:58:51 +02005653 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005654 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005655 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02005656 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02005657 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005658 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005659
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005660 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02005661 if (module->version < 2) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005662 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "action");
Michal Vaskobb174852016-07-25 11:00:21 +02005663 return NULL;
5664 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005665 for (node = parent; node; node = lys_parent(node)) {
Radek Krejcia3b19f72016-09-30 13:02:45 +02005666 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005667 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005668 LOGVAL(LYE_INPAR, LY_VLOG_LYS, parent, strnodetype(node->nodetype), "action");
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005669 return NULL;
5670 }
5671 }
5672 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005673
Radek Krejcie0674f82015-06-15 13:58:51 +02005674 /* init */
5675 memset(&root, 0, sizeof root);
5676
Michal Vasko38d01f72015-06-15 09:41:06 +02005677 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01005678 if (!rpc) {
5679 LOGMEM;
5680 return NULL;
5681 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005682 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02005683 rpc->prev = (struct lys_node *)rpc;
5684 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02005685
Radek Krejci07d0fb92017-01-13 14:11:05 +01005686 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005687 goto error;
5688 }
5689
Radek Krejcia9544502015-08-14 08:24:29 +02005690 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5691
Radek Krejcic189a952016-07-11 15:27:07 +02005692 /* insert the node into the schema tree */
5693 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5694 goto error;
5695 }
5696
Michal Vasko38d01f72015-06-15 09:41:06 +02005697 /* process rpc's specific children */
5698 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005699 if (strcmp(sub->ns->value, LY_NSYIN)) {
5700 /* extension */
5701 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005702 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01005703 } else if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02005704 if (c_input) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005705 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005706 goto error;
5707 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02005708 c_input++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005709 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005710 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005711 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02005712 if (c_output) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005713 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005714 goto error;
5715 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02005716 c_output++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005717 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005718 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005719
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005720 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02005721 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005722 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005723 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005724
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005725 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005726 } else if (!strcmp(sub->name, "typedef")) {
5727 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005728 } else if (!strcmp(sub->name, "if-feature")) {
5729 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02005730 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005731 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005732 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005733 }
5734 }
5735
5736 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5737 if (c_tpdf) {
5738 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005739 if (!rpc->tpdf) {
5740 LOGMEM;
5741 goto error;
5742 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005743 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005744 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005745 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
5746 if (!rpc->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005747 LOGMEM;
5748 goto error;
5749 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005750 }
Radek Krejcie534c132016-11-23 13:32:31 +01005751 if (c_ext) {
5752 rpc->ext = calloc(c_ext, sizeof *rpc->ext);
5753 if (!rpc->ext) {
5754 LOGMEM;
5755 goto error;
5756 }
5757 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005758
Radek Krejcie534c132016-11-23 13:32:31 +01005759 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5760 if (strcmp(sub->ns->value, LY_NSYIN)) {
5761 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005762 r = lyp_yin_fill_ext(retval, LYEXT_PAR_NODE, 0, 0, module, sub, &retval->ext, retval->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01005763 retval->ext_size++;
5764 if (r) {
5765 goto error;
5766 }
5767 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005768 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
5769 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02005770 if (r) {
5771 goto error;
5772 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005773 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005774 r = fill_yin_iffeature(retval, 0, sub, &rpc->iffeature[rpc->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005775 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005776 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005777 goto error;
5778 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005779 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005780 }
5781
5782 /* last part - process data nodes */
5783 LY_TREE_FOR_SAFE(root.child, next, sub) {
5784 if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005785 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005786 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005787 node = read_yin_input_output(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005788 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005789 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005790 goto error;
5791 }
Radek Krejci73adb602015-07-02 18:07:40 +02005792
Michal Vasko345da0a2015-12-02 10:35:55 +01005793 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005794 }
5795
Michal Vasko38d01f72015-06-15 09:41:06 +02005796 return retval;
5797
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005798error:
Michal Vasko38d01f72015-06-15 09:41:06 +02005799
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005800 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02005801 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005802 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005803 }
5804
5805 return NULL;
5806}
5807
Michal Vasko0d343d12015-08-24 14:57:36 +02005808/* logs directly
5809 *
Radek Krejci74705112015-06-05 10:25:44 +02005810 * resolve - referenced grouping should be bounded to the namespace (resolved)
5811 * only when uses does not appear in grouping. In a case of grouping's uses,
5812 * we just get information but we do not apply augment or refine to it.
5813 */
Radek Krejci76512572015-08-04 09:47:08 +02005814static struct lys_node *
Radek Krejci3440cc52016-06-23 17:03:59 +02005815read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02005816{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005817 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02005818 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005819 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005820 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01005821 int c_ref = 0, c_aug = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005822 int r;
Radek Krejci74705112015-06-05 10:25:44 +02005823
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005824 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01005825 if (!uses) {
5826 LOGMEM;
5827 return NULL;
5828 }
Radek Krejci76512572015-08-04 09:47:08 +02005829 uses->nodetype = LYS_USES;
5830 uses->prev = (struct lys_node *)uses;
5831 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02005832
Radek Krejcia9544502015-08-14 08:24:29 +02005833 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005834 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02005835
Radek Krejci07d0fb92017-01-13 14:11:05 +01005836 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005837 goto error;
5838 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005839
Radek Krejcia9544502015-08-14 08:24:29 +02005840 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5841
Radek Krejcic189a952016-07-11 15:27:07 +02005842 /* insert the node into the schema tree */
5843 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5844 goto error;
5845 }
5846
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005847 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02005848 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005849 if (strcmp(sub->ns->value, LY_NSYIN)) {
5850 /* extension */
5851 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005852 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01005853 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005854 c_ref++;
5855 } else if (!strcmp(sub->name, "augment")) {
5856 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005857 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02005858 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005859 } else if (!strcmp(sub->name, "when")) {
5860 if (uses->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005861 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005862 goto error;
5863 }
5864
Radek Krejci5323b492017-01-16 15:40:11 +01005865 uses->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005866 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005867 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005868 goto error;
5869 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005870 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005871 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005872 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005873 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005874 }
5875 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005876
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005877 /* process properties with cardinality 0..n */
5878 if (c_ref) {
5879 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01005880 if (!uses->refine) {
5881 LOGMEM;
5882 goto error;
5883 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005884 }
5885 if (c_aug) {
5886 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01005887 if (!uses->augment) {
5888 LOGMEM;
5889 goto error;
5890 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005891 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005892 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005893 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
5894 if (!uses->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005895 LOGMEM;
5896 goto error;
5897 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005898 }
Radek Krejcie534c132016-11-23 13:32:31 +01005899 if (c_ext) {
5900 uses->ext = calloc(c_ext, sizeof *uses->ext);
5901 if (!uses->ext) {
5902 LOGMEM;
5903 goto error;
5904 }
5905 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005906
Radek Krejcie534c132016-11-23 13:32:31 +01005907 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5908 if (strcmp(sub->ns->value, LY_NSYIN)) {
5909 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005910 r = lyp_yin_fill_ext(retval, LYEXT_PAR_NODE, 0, 0, module, sub, &retval->ext, retval->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01005911 retval->ext_size++;
5912 if (r) {
5913 goto error;
5914 }
5915 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02005916 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005917 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005918 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005919 goto error;
5920 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005921 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005922 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
5923 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005924 if (r) {
5925 goto error;
5926 }
5927 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005928 r = fill_yin_iffeature(retval, 0, sub, &uses->iffeature[uses->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005929 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005930 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005931 goto error;
5932 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005933 }
5934 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005935
Radek Krejci48464ed2016-03-17 15:44:09 +01005936 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005937 goto error;
5938 }
Radek Krejci74705112015-06-05 10:25:44 +02005939
Michal Vasko508a50d2016-09-07 14:50:33 +02005940 /* check XPath dependencies */
5941 if (uses->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5942 goto error;
5943 }
5944
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005945 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005946
5947error:
5948
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005949 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005950
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005951 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005952}
5953
Michal Vasko0d343d12015-08-24 14:57:36 +02005954/* logs directly
5955 *
5956 * common code for yin_read_module() and yin_read_submodule()
5957 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005958static int
Radek Krejcic071c542016-01-27 14:57:51 +01005959read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
5960 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005961{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005962 struct ly_ctx *ctx = module->ctx;
Radek Krejcie534c132016-11-23 13:32:31 +01005963 struct lyxml_elem *next, *child, *child2, root, grps, augs, exts;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005964 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005965 struct lys_module *trg;
Pavol Vican974377b2016-03-23 00:38:53 +01005966 struct lys_include inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005967 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01005968 int i, r;
Radek Krejci4dcd3392016-06-22 10:28:40 +02005969 size_t size;
Radek Krejcic071c542016-01-27 14:57:51 +01005970 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005971 /* counters */
Radek Krejcie534c132016-11-23 13:32:31 +01005972 int c_imp = 0, c_rev = 0, c_tpdf = 0, c_ident = 0, c_inc = 0, c_aug = 0, c_ftrs = 0, c_dev = 0;
5973 int c_ext = 0, c_extinst = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005974
Radek Krejcic071c542016-01-27 14:57:51 +01005975 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02005976 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01005977
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005978 /* init */
5979 memset(&root, 0, sizeof root);
5980 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02005981 memset(&augs, 0, sizeof augs);
Radek Krejcie534c132016-11-23 13:32:31 +01005982 memset(&exts, 0, sizeof exts);
Radek Krejcie0674f82015-06-15 13:58:51 +02005983
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005984 /*
5985 * in the first run, we process elements with cardinality of 1 or 0..1 and
5986 * count elements with cardinality 0..n. Data elements (choices, containers,
5987 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
5988 * need have all top-level and groupings already prepared at that time. In
5989 * the middle loop, we process other elements with carinality of 0..n since
5990 * we need to allocate arrays to store them.
5991 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005992 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01005993 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005994 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005995 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005996 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01005997 } else if (strcmp(child->ns->value, LY_NSYIN)) {
5998 /* possible extension instance */
5999 lyxml_unlink_elem(module->ctx, child, 2);
6000 lyxml_add_child(module->ctx, &exts, child);
6001 c_extinst++;
6002 } else if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006003 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006004 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006005 goto error;
6006 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006007 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006008 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01006009 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006010 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006011 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006012 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006013 goto error;
6014 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006015 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01006016 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006017 goto error;
6018 }
6019 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01006020 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006021 } else if (submodule && !strcmp(child->name, "belongs-to")) {
6022 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006023 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006024 goto error;
6025 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006026 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01006027 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006028 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006029 goto error;
6030 }
Radek Krejcif3886932015-06-04 17:36:06 +02006031
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006032 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006033 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006034 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006035 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006036 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006037 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006038 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006039 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006040 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006041 goto error;
6042 }
6043 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006044 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006045 /* check here differs from a generic prefix check, since this prefix
6046 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02006047 */
Radek Krejci48464ed2016-03-17 15:44:09 +01006048 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006049 goto error;
6050 }
Radek Krejcic071c542016-01-27 14:57:51 +01006051 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02006052
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006053 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01006054 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02006055
6056 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006057 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006058 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006059 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006060 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006061 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006062 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006063 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006064 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006065 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006066 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006067 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02006068 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006069 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01006070 lyxml_unlink_elem(ctx, child, 2);
6071 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006072
Radek Krejci1d82ef62015-08-07 14:44:40 +02006073 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006074 c_ftrs++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006076 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006077 } else if (!strcmp(child->name, "container") ||
6078 !strcmp(child->name, "leaf-list") ||
6079 !strcmp(child->name, "leaf") ||
6080 !strcmp(child->name, "list") ||
6081 !strcmp(child->name, "choice") ||
6082 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006083 !strcmp(child->name, "anyxml") ||
6084 !strcmp(child->name, "rpc") ||
6085 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006086 lyxml_unlink_elem(ctx, child, 2);
6087 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006088
Radek Krejci1d82ef62015-08-07 14:44:40 +02006089 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006090 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01006091 lyxml_unlink_elem(ctx, child, 2);
6092 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006093
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006094 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006095 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006096 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006097 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006098 goto error;
6099 }
Radek Krejcic071c542016-01-27 14:57:51 +01006100 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006101 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006102 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006103 goto error;
6104 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006105 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006106 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006107 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006108 goto error;
6109 }
Radek Krejcic071c542016-01-27 14:57:51 +01006110 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006111 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006112 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006113 goto error;
6114 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006115 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006116 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006117 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006118 goto error;
6119 }
Radek Krejcic071c542016-01-27 14:57:51 +01006120 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006121 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006122 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006123 goto error;
6124 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006125 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006126 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006127 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006128 goto error;
6129 }
Radek Krejcic071c542016-01-27 14:57:51 +01006130 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006131 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006132 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006133 goto error;
6134 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006135 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006136 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006137 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006138 goto error;
6139 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006140 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02006141 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006142 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006143 goto error;
6144 }
Radek Krejcic071c542016-01-27 14:57:51 +01006145 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006146 if (!strcmp(value, "1")) {
6147 if (submodule) {
6148 if (module->version > 1) {
6149 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6150 goto error;
6151 }
6152 } else {
6153 module->version = 1;
6154 }
6155 } else {
6156 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006157 if (module->version < 2) {
Michal Vasko88de3e42016-06-29 11:05:32 +02006158 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6159 goto error;
6160 }
6161 } else {
6162 module->version = 2;
6163 }
6164 }
6165
Michal Vasko345da0a2015-12-02 10:35:55 +01006166 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006167
Radek Krejci1d82ef62015-08-07 14:44:40 +02006168 } else if (!strcmp(child->name, "extension")) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09006169 c_ext++;
Radek Krejci5166a892015-07-02 16:44:24 +02006170
Radek Krejcia1a6b762016-11-14 09:53:38 +09006171 } else if (!strcmp(child->name, "deviation")) {
6172 c_dev++;
6173
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006174 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01006175 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006176 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006177 }
6178 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006179
Radek Krejcic071c542016-01-27 14:57:51 +01006180 /* check for mandatory statements */
6181 if (submodule && !submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006182 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01006183 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01006184 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006185 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006186 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006187 goto error;
6188 }
6189 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006190 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006191 goto error;
6192 }
6193 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02006194
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006195 /* allocate arrays for elements with cardinality of 0..n */
6196 if (c_imp) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02006197 size = (c_imp * sizeof *trg->imp) + sizeof(void*);
6198 trg->imp = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01006199 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01006200 LOGMEM;
6201 goto error;
6202 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02006203 /* set stop block for possible realloc */
6204 trg->imp[c_imp].module = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006205 }
6206 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006207 trg->rev = calloc(c_rev, sizeof *trg->rev);
6208 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01006209 LOGMEM;
6210 goto error;
6211 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006212 }
6213 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01006214 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
6215 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01006216 LOGMEM;
6217 goto error;
6218 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006219 }
6220 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01006221 trg->ident = calloc(c_ident, sizeof *trg->ident);
6222 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01006223 LOGMEM;
6224 goto error;
6225 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006226 }
6227 if (c_inc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02006228 size = (c_inc * sizeof *trg->inc) + sizeof(void*);
6229 trg->inc = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01006230 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01006231 LOGMEM;
6232 goto error;
6233 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02006234 /* set stop block for possible realloc */
6235 trg->inc[c_inc].submodule = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006236 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006237 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01006238 trg->augment = calloc(c_aug, sizeof *trg->augment);
6239 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01006240 LOGMEM;
6241 goto error;
6242 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006243 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006244 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01006245 trg->features = calloc(c_ftrs, sizeof *trg->features);
6246 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01006247 LOGMEM;
6248 goto error;
6249 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006250 }
Radek Krejcieb00f512015-07-01 16:44:58 +02006251 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006252 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
6253 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01006254 LOGMEM;
6255 goto error;
6256 }
Radek Krejcieb00f512015-07-01 16:44:58 +02006257 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09006258 if (c_ext) {
6259 trg->extensions = calloc(c_ext, sizeof *trg->extensions);
6260 if (!trg->extensions) {
6261 LOGMEM;
6262 goto error;
6263 }
6264 }
Radek Krejcie534c132016-11-23 13:32:31 +01006265 if (c_extinst) {
6266 trg->ext = calloc(c_extinst, sizeof *trg->ext);
6267 if (!trg->ext) {
6268 LOGMEM;
6269 goto error;
6270 }
6271 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006272
Michal Vasko2f7925f2015-10-21 15:06:56 +02006273 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
6274 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02006275 if (!strcmp(child->name, "import")) {
Radek Krejcie534c132016-11-23 13:32:31 +01006276 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size], unres);
Radek Krejcic071c542016-01-27 14:57:51 +01006277 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006278 if (r) {
6279 goto error;
6280 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006281
Radek Krejci1d82ef62015-08-07 14:44:40 +02006282 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006283 memset(&inc, 0, sizeof inc);
6284 /* 1) pass module, not trg, since we want to pass the main module
6285 * 2) we cannot pass directly the structure in the array since
6286 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01006287 r = fill_yin_include(module, submodule, child, &inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02006288 if (!r) {
6289 /* success, copy the filled data into the final array */
Radek Krejci4dcd3392016-06-22 10:28:40 +02006290 memcpy(&trg->inc[trg->inc_size], &inc, sizeof inc);
6291 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02006292 } else if (r == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006293 goto error;
6294 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006295
Radek Krejci1d82ef62015-08-07 14:44:40 +02006296 } else if (!strcmp(child->name, "revision")) {
6297 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01006298 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006299 goto error;
6300 }
Radek Krejcic071c542016-01-27 14:57:51 +01006301 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006302 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01006303 for (i = 0; i < trg->rev_size; i++) {
6304 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006305 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
6306 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006307 }
6308 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006309
Radek Krejci1d82ef62015-08-07 14:44:40 +02006310 LY_TREE_FOR(child->child, child2) {
6311 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006312 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006313 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006314 goto error;
6315 }
Radek Krejcic071c542016-01-27 14:57:51 +01006316 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
6317 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006318 goto error;
6319 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006320 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006321 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006322 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006323 goto error;
6324 }
Radek Krejcic071c542016-01-27 14:57:51 +01006325 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
6326 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006327 goto error;
6328 }
6329 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01006330 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006331 goto error;
6332 }
6333 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006334
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006335 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01006336 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006337 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01006338 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01006339 if (!value) {
6340 LOGMEM;
6341 goto error;
6342 }
Radek Krejcic071c542016-01-27 14:57:51 +01006343 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
6344 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006345 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02006346
Radek Krejci749190d2016-02-18 16:26:25 +01006347 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01006348 value = trg->rev[0].dsc;
6349 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
6350 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006351 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006352
Radek Krejci749190d2016-02-18 16:26:25 +01006353 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01006354 value = trg->rev[0].ref;
6355 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
6356 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006357 }
6358 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006359
Radek Krejcic071c542016-01-27 14:57:51 +01006360 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006361
Radek Krejci1d82ef62015-08-07 14:44:40 +02006362 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006363 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
6364 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006365 if (r) {
6366 goto error;
6367 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006368
Radek Krejci1d82ef62015-08-07 14:44:40 +02006369 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006370 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
6371 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006372 if (r) {
6373 goto error;
6374 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006375
Radek Krejci1d82ef62015-08-07 14:44:40 +02006376 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006377 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
6378 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006379 if (r) {
6380 goto error;
6381 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006382
Radek Krejcia1a6b762016-11-14 09:53:38 +09006383 } else if (!strcmp(child->name, "extension")) {
Radek Krejcie534c132016-11-23 13:32:31 +01006384 r = fill_yin_extension(trg, child, &trg->extensions[trg->extensions_size], unres);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006385 trg->extensions_size++;
6386 if (r) {
6387 goto error;
6388 }
6389
Radek Krejci1d82ef62015-08-07 14:44:40 +02006390 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006391 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
6392 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02006393 if (r) {
6394 goto error;
6395 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006396 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006397 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006398
Radek Krejcib8f98c12016-06-24 10:30:46 +02006399 if (!submodule) {
6400 /* update the size of the arrays, they can be smaller due to possible duplicities
Radek Krejci4dcd3392016-06-22 10:28:40 +02006401 * found in submodules */
Radek Krejcib8f98c12016-06-24 10:30:46 +02006402 if (module->inc_size) {
6403 module->inc = ly_realloc(module->inc, module->inc_size * sizeof *module->inc);
6404 if (!module->inc) {
6405 LOGMEM;
6406 goto error;
6407 }
6408 }
6409 if (module->imp_size) {
6410 module->imp = ly_realloc(module->imp, module->imp_size * sizeof *module->imp);
6411 if (!module->imp) {
6412 LOGMEM;
6413 goto error;
6414 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02006415 }
6416 }
Radek Krejcic071c542016-01-27 14:57:51 +01006417
Radek Krejcie534c132016-11-23 13:32:31 +01006418 /* process extension instances */
6419 LY_TREE_FOR_SAFE(exts.child, next, child) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01006420 r = lyp_yin_fill_ext(trg, LYEXT_PAR_MODULE, 0, 0, module, child, &trg->ext, trg->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01006421 trg->ext_size++;
6422 if (r) {
6423 goto error;
6424 }
6425 }
6426
6427
Radek Krejcif5be10f2015-06-16 13:29:36 +02006428 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01006429 * refer to them. Submodule's data nodes are stored in the
6430 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006431 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006432 LY_TREE_FOR_SAFE(grps.child, next, child) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006433 node = read_yin_grouping(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006434 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006435 goto error;
6436 }
Radek Krejci74705112015-06-05 10:25:44 +02006437
Michal Vasko345da0a2015-12-02 10:35:55 +01006438 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006439 }
Radek Krejci74705112015-06-05 10:25:44 +02006440
Radek Krejcif5be10f2015-06-16 13:29:36 +02006441 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006442 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02006443
Radek Krejci1d82ef62015-08-07 14:44:40 +02006444 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006445 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006446 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006447 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006448 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006449 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006450 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006451 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006452 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006453 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006454 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02006455 node = read_yin_uses(trg, NULL, child, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006456 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02006457 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 1, unres);
6458 } else if (!strcmp(child->name, "anydata")) {
6459 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006460 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006461 node = read_yin_rpc_action(trg, NULL, child, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006462 } else if (!strcmp(child->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006463 node = read_yin_notif(trg, NULL, child, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006464 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006465 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006466 goto error;
6467 }
Radek Krejci25d782a2015-05-22 15:03:23 +02006468
Michal Vasko345da0a2015-12-02 10:35:55 +01006469 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006470 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006471
Michal Vasko2f7925f2015-10-21 15:06:56 +02006472 /* ... and finally augments (last, so we can augment our data, for instance) */
6473 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01006474 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
6475 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02006476
Michal Vasko2f7925f2015-10-21 15:06:56 +02006477 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02006478 goto error;
6479 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006480 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02006481 }
6482
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006483 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02006484
6485error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006486 /* cleanup */
6487 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006488 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006489 }
6490 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006491 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006492 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006493 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006494 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006495 }
Radek Krejcie534c132016-11-23 13:32:31 +01006496 while (exts.child) {
6497 lyxml_free(module->ctx, exts.child);
6498 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006499
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006500 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02006501}
6502
Michal Vasko0d343d12015-08-24 14:57:36 +02006503/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01006504struct lys_submodule *
6505yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02006506{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006507 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01006508 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006509 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02006510
Michal Vasko5a721fd2016-02-16 12:16:48 +01006511 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02006512
Radek Krejci722b0072016-02-01 17:09:45 +01006513 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006514 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01006515 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006516 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006517
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006518 /* check root element */
6519 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006520 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006521 goto error;
6522 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006523
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006524 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01006525 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006526 goto error;
6527 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006528
Michal Vasko5a721fd2016-02-16 12:16:48 +01006529 submodule = calloc(1, sizeof *submodule);
6530 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006531 LOGMEM;
6532 goto error;
6533 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006534
Michal Vasko5a721fd2016-02-16 12:16:48 +01006535 submodule->ctx = module->ctx;
6536 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
6537 submodule->type = 1;
6538 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02006539
Michal Vasko5a721fd2016-02-16 12:16:48 +01006540 LOGVRB("Reading submodule \"%s\".", submodule->name);
6541 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006542 goto error;
6543 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006544
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006545 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01006546 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02006547
Michal Vasko5a721fd2016-02-16 12:16:48 +01006548 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006549 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02006550
6551error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006552 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01006553 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01006554 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01006555
Michal Vasko5a721fd2016-02-16 12:16:48 +01006556 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01006557 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01006558 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01006559 }
6560
Michal Vasko5a721fd2016-02-16 12:16:48 +01006561 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01006562
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006563 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
6564 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006565 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006566 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02006567}
6568
Michal Vasko0d343d12015-08-24 14:57:36 +02006569/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02006570struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01006571yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02006572{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006573 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01006574 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006575 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006576 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02006577
Radek Krejcic071c542016-01-27 14:57:51 +01006578 unres = calloc(1, sizeof *unres);
6579 if (!unres) {
6580 LOGMEM;
6581 return NULL;
6582 }
6583
Radek Krejci722b0072016-02-01 17:09:45 +01006584 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006585 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01006586 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006587 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006588
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006589 /* check root element */
6590 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci9a909bd2016-10-24 15:45:51 +02006591 if (ly_strequal("submodule", yin->name, 0)) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01006592 LOGVAL(LYE_SUBMODULE, LY_VLOG_NONE, NULL);
6593 } else {
6594 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci9a909bd2016-10-24 15:45:51 +02006595 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006596 goto error;
6597 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006598
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006599 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01006600 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006601 goto error;
6602 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006603
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006604 module = calloc(1, sizeof *module);
6605 if (!module) {
6606 LOGMEM;
6607 goto error;
6608 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006609
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006610 module->ctx = ctx;
6611 module->name = lydict_insert(ctx, value, strlen(value));
6612 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02006613 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02006614
Michal Vasko9f258e42016-02-11 11:36:27 +01006615 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01006616 if (read_sub_module(module, NULL, yin, unres)) {
6617 goto error;
6618 }
6619
6620 /* resolve rest of unres items */
6621 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006622 goto error;
6623 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006624
Radek Krejciff4874d2016-03-07 12:30:50 +01006625 if (revision) {
6626 /* check revision of the parsed model */
6627 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01006628 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
6629 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01006630 goto error;
6631 }
6632 }
6633
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006634 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01006635 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006636 }
Radek Krejci63a91a92015-07-29 13:31:04 +02006637
Radek Krejci27fe55e2016-09-13 17:13:35 +02006638 if (module->deviation_size && !module->implemented) {
6639 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
6640 /* deviations always causes target to be made implemented,
6641 * but augents and leafrefs not, so we have to apply them now */
6642 if (lys_set_implemented(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02006643 goto error;
6644 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006645 }
6646
Michal Vasko345da0a2015-12-02 10:35:55 +01006647 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01006648 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01006649 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006650 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006651
6652error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006653 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01006654 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01006655 unres_schema_free(module, &unres);
6656
6657 if (!module) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01006658 if (ly_vecode != LYVE_SUBMODULE) {
6659 LOGERR(ly_errno, "Module parsing failed.");
6660 }
Radek Krejcib8c07b82016-02-12 11:11:55 +01006661 return NULL;
6662 }
6663
6664 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006665
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006666 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01006667 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006668 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006669}