blob: 176b25cb3bdbc62fadb12c095cef059b588f35c0 [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,
Radek Krejci7212e0a2017-03-08 15:58:22 +010051 int options, 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,
Radek Krejci7212e0a2017-03-08 15:58:22 +010053 int options, 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,
Radek Krejci7212e0a2017-03-08 15:58:22 +010057 int options, 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,
Radek Krejci7212e0a2017-03-08 15:58:22 +010063 int options, 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 Krejci7212e0a2017-03-08 15:58:22 +010065 int options, 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,
Radek Krejci7212e0a2017-03-08 15:58:22 +010067 int options, 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,
Radek Krejci7212e0a2017-03-08 15:58:22 +010069 int options, 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,
Radek Krejci7212e0a2017-03-08 15:58:22 +010071 int options, 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;
Radek Krejcia7db9702017-01-20 12:55:14 +010090 info->mod = module;
Radek Krejci07d0fb92017-01-13 14:11:05 +010091 info->parent_type = parent_type;
92 info->substmt = substmt;
93 info->substmt_index = substmt_index;
Radek Krejci2b999ac2017-01-18 16:22:12 +010094 info->ext_index = ext_index;
Radek Krejci07d0fb92017-01-13 14:11:05 +010095
96 if (unres_schema_add_node(module, unres, ext, UNRES_EXT, (struct lys_node *)info) == -1) {
97 return EXIT_FAILURE;
98 }
99
100 return EXIT_SUCCESS;
101}
102
Michal Vasko0d343d12015-08-24 14:57:36 +0200103/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200104static const char *
105read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +0200106{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200107 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200108
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200109 /* there should be <text> child */
110 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
Radek Krejci218436d2016-02-10 12:54:06 +0100111 LOGERR(LY_EVALID, "Expected \"%s\" element in \"%s\" element.", name, node->name);
Radek Krejci48464ed2016-03-17 15:44:09 +0100112 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, node->name);
Radek Krejci218436d2016-02-10 12:54:06 +0100113 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200114 } else if (node->child->content) {
115 len = strlen(node->child->content);
116 return lydict_insert(ctx, node->child->content, len);
Radek Krejci218436d2016-02-10 12:54:06 +0100117 } else {
118 return lydict_insert(ctx, "", 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200119 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200120}
121
Radek Krejci8d6b7422017-02-03 14:42:13 +0100122int
123lyp_yin_parse_subnode_ext(struct lys_module *mod, void *elem, LYEXT_PAR elem_type,
Radek Krejciac00b2a2017-01-17 14:05:00 +0100124 struct lyxml_elem *yin, LYEXT_SUBSTMT type, uint8_t i, struct unres_schema *unres)
Radek Krejcie534c132016-11-23 13:32:31 +0100125{
Radek Krejci07d0fb92017-01-13 14:11:05 +0100126 void *reallocated;
127 struct lyxml_elem *next, *child;
128 int r;
129 struct lys_ext_instance ***ext;
130 uint8_t *ext_size;
Radek Krejcie534c132016-11-23 13:32:31 +0100131
Radek Krejci07d0fb92017-01-13 14:11:05 +0100132 switch (elem_type) {
133 case LYEXT_PAR_MODULE:
134 ext_size = &((struct lys_module *)elem)->ext_size;
135 ext = &((struct lys_module *)elem)->ext;
136 break;
Radek Krejci95f22ae2017-01-20 14:25:53 +0100137 case LYEXT_PAR_IMPORT:
138 ext_size = &((struct lys_import *)elem)->ext_size;
139 ext = &((struct lys_import *)elem)->ext;
140 break;
141 case LYEXT_PAR_INCLUDE:
142 ext_size = &((struct lys_include *)elem)->ext_size;
143 ext = &((struct lys_include *)elem)->ext;
144 break;
145 case LYEXT_PAR_REVISION:
146 ext_size = &((struct lys_revision *)elem)->ext_size;
147 ext = &((struct lys_revision *)elem)->ext;
148 break;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100149 case LYEXT_PAR_NODE:
150 ext_size = &((struct lys_node *)elem)->ext_size;
151 ext = &((struct lys_node *)elem)->ext;
152 break;
153 case LYEXT_PAR_IDENT:
154 ext_size = &((struct lys_ident *)elem)->ext_size;
155 ext = &((struct lys_ident *)elem)->ext;
156 break;
Radek Krejci47f7ea52017-01-23 13:14:09 +0100157 case LYEXT_PAR_TYPE:
158 ext_size = &((struct lys_type *)elem)->ext_size;
159 ext = &((struct lys_type *)elem)->ext;
160 break;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100161 case LYEXT_PAR_TYPE_BIT:
162 ext_size = &((struct lys_type_bit *)elem)->ext_size;
163 ext = &((struct lys_type_bit *)elem)->ext;
164 break;
165 case LYEXT_PAR_TYPE_ENUM:
166 ext_size = &((struct lys_type_enum *)elem)->ext_size;
167 ext = &((struct lys_type_enum *)elem)->ext;
168 break;
169 case LYEXT_PAR_TPDF:
170 ext_size = &((struct lys_tpdf *)elem)->ext_size;
171 ext = &((struct lys_tpdf *)elem)->ext;
172 break;
173 case LYEXT_PAR_EXT:
174 ext_size = &((struct lys_ext *)elem)->ext_size;
175 ext = &((struct lys_ext *)elem)->ext;
176 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +0100177 case LYEXT_PAR_EXTINST:
178 ext_size = &((struct lys_ext_instance *)elem)->ext_size;
179 ext = &((struct lys_ext_instance *)elem)->ext;
180 break;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100181 case LYEXT_PAR_FEATURE:
182 ext_size = &((struct lys_feature *)elem)->ext_size;
183 ext = &((struct lys_feature *)elem)->ext;
184 break;
185 case LYEXT_PAR_REFINE:
186 ext_size = &((struct lys_refine *)elem)->ext_size;
187 ext = &((struct lys_refine *)elem)->ext;
188 break;
Radek Krejcifdc0d702017-01-23 15:58:38 +0100189 case LYEXT_PAR_RESTR:
Radek Krejcifccd1442017-01-16 10:26:57 +0100190 ext_size = &((struct lys_restr *)elem)->ext_size;
191 ext = &((struct lys_restr *)elem)->ext;
192 break;
Radek Krejci5323b492017-01-16 15:40:11 +0100193 case LYEXT_PAR_WHEN:
194 ext_size = &((struct lys_when *)elem)->ext_size;
195 ext = &((struct lys_when *)elem)->ext;
196 break;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +0100197 case LYEXT_PAR_DEVIATE:
198 ext_size = &((struct lys_deviate *)elem)->ext_size;
199 ext = &((struct lys_deviate *)elem)->ext;
200 break;
201 case LYEXT_PAR_DEVIATION:
202 ext_size = &((struct lys_deviation *)elem)->ext_size;
203 ext = &((struct lys_deviation *)elem)->ext;
204 break;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100205 default:
Radek Krejcifccd1442017-01-16 10:26:57 +0100206 LOGERR(LY_EINT, "parent type %d", elem_type);
Radek Krejcie534c132016-11-23 13:32:31 +0100207 return EXIT_FAILURE;
208 }
209
Radek Krejcifccd1442017-01-16 10:26:57 +0100210 if (type == LYEXT_SUBSTMT_SELF) {
211 /* parse for the statement self, not for the substatement */
212 child = yin;
213 next = NULL;
214 goto parseext;
215 }
216
Radek Krejci07d0fb92017-01-13 14:11:05 +0100217 LY_TREE_FOR_SAFE(yin->child, next, child) {
218 if (!strcmp(child->ns->value, LY_NSYIN)) {
219 /* skip the regular YIN nodes */
220 continue;
221 }
222
223 /* parse it as extension */
Radek Krejcifccd1442017-01-16 10:26:57 +0100224parseext:
Radek Krejci07d0fb92017-01-13 14:11:05 +0100225
226 /* first, allocate a space for the extension instance in the parent elem */
227 reallocated = realloc(*ext, (1 + (*ext_size)) * sizeof **ext);
228 if (!reallocated) {
229 LOGMEM;
230 return EXIT_FAILURE;
231 }
232 (*ext) = reallocated;
233
234 /* init memory */
235 (*ext)[(*ext_size)] = NULL;
236
237 /* parse YIN data */
Radek Krejci2b999ac2017-01-18 16:22:12 +0100238 r = lyp_yin_fill_ext(elem, elem_type, type, i, mod, child, &(*ext), (*ext_size), unres);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100239 (*ext_size)++;
240 if (r) {
241 return EXIT_FAILURE;
242 }
243
Radek Krejcifccd1442017-01-16 10:26:57 +0100244 /* done - do not free the child, it is unlinked in lyp_yin_fill_ext */
Radek Krejci07d0fb92017-01-13 14:11:05 +0100245 }
246
Radek Krejcie534c132016-11-23 13:32:31 +0100247 return EXIT_SUCCESS;
248}
249
Michal Vasko0d343d12015-08-24 14:57:36 +0200250/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200251static int
Radek Krejci9de2c042016-10-19 16:53:06 +0200252fill_yin_iffeature(struct lys_node *parent, int parent_is_feature, struct lyxml_elem *yin, struct lys_iffeature *iffeat,
253 struct unres_schema *unres)
Michal Vasko1d337e12016-02-15 12:32:04 +0100254{
Radek Krejci5323b492017-01-16 15:40:11 +0100255 int r, c_ext = 0;
Michal Vasko1d337e12016-02-15 12:32:04 +0100256 const char *value;
Radek Krejci5323b492017-01-16 15:40:11 +0100257 struct lyxml_elem *node, *next;
Michal Vasko1d337e12016-02-15 12:32:04 +0100258
259 GETVAL(value, yin, "name");
Michal Vasko97b32be2016-07-25 10:59:53 +0200260
261 if ((lys_node_module(parent)->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
262 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
Radek Krejci9ff0a922016-07-14 13:08:05 +0200263error:
Michal Vasko1d337e12016-02-15 12:32:04 +0100264 return EXIT_FAILURE;
265 }
266
Michal Vasko56d082c2016-10-25 14:00:42 +0200267 if (!(value = transform_iffeat_schema2json(parent->module, value))) {
Michal Vasko1d337e12016-02-15 12:32:04 +0100268 return EXIT_FAILURE;
269 }
270
Radek Krejci9de2c042016-10-19 16:53:06 +0200271 r = resolve_iffeature_compile(iffeat, value, parent, parent_is_feature, unres);
Michal Vasko1d337e12016-02-15 12:32:04 +0100272 lydict_remove(parent->module->ctx, value);
Radek Krejci9ff0a922016-07-14 13:08:05 +0200273 if (r) {
274 return EXIT_FAILURE;
Michal Vasko1d337e12016-02-15 12:32:04 +0100275 }
276
Radek Krejci5323b492017-01-16 15:40:11 +0100277 LY_TREE_FOR_SAFE(yin->child, next, node) {
278 if (!node->ns) {
279 /* garbage */
280 lyxml_free(parent->module->ctx, node);
281 } else if (strcmp(node->ns->value, LY_NSYIN)) {
282 /* extension */
283 c_ext++;
284 } else {
285 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "if-feature");
286 return EXIT_FAILURE;
287 }
288 }
289 if (c_ext) {
290 iffeat->ext = calloc(c_ext, sizeof *iffeat->ext);
291 if (!iffeat->ext) {
292 LOGMEM;
293 return EXIT_FAILURE;
294 }
295 LY_TREE_FOR_SAFE(yin->child, next, node) {
296 /* extensions */
297 r = lyp_yin_fill_ext(iffeat, LYEXT_PAR_IDENT, 0, 0, parent->module, node,
Radek Krejci2b999ac2017-01-18 16:22:12 +0100298 &iffeat->ext, iffeat->ext_size, unres);
Radek Krejci5323b492017-01-16 15:40:11 +0100299 iffeat->ext_size++;
300 if (r) {
301 return EXIT_FAILURE;
302 }
303 }
304 }
305
Radek Krejci9ff0a922016-07-14 13:08:05 +0200306 return EXIT_SUCCESS;
Michal Vasko1d337e12016-02-15 12:32:04 +0100307}
308
309/* logs directly */
310static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200311fill_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 +0200312{
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200313 struct lyxml_elem *node, *next;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200314 const char *value;
Radek Krejci018f1f52016-08-03 16:01:20 +0200315 int rc;
Radek Krejcie534c132016-11-23 13:32:31 +0100316 int c_ftrs = 0, c_base = 0, c_ext = 0;
Radek Krejci18a44882017-01-23 13:47:29 +0100317 void *reallocated;
Radek Krejci04581c62015-05-22 21:24:00 +0200318
Michal Vasko4cfcd252015-08-03 14:31:10 +0200319 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100320 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200321
Radek Krejci07d0fb92017-01-13 14:11:05 +0100322 if (read_yin_common(module, NULL, ident, LYEXT_PAR_IDENT, yin, OPT_IDENT | OPT_MODULE, unres)) {
Radek Krejci18a44882017-01-23 13:47:29 +0100323 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200324 }
Radek Krejci04581c62015-05-22 21:24:00 +0200325
Pavol Vicand6cda452016-07-13 15:08:29 +0200326 if (dup_identities_check(ident->name, module)) {
Radek Krejci18a44882017-01-23 13:47:29 +0100327 goto error;
Pavol Vicand6cda452016-07-13 15:08:29 +0200328 }
329
Radek Krejcie534c132016-11-23 13:32:31 +0100330 LY_TREE_FOR(yin->child, node) {
331 if (strcmp(node->ns->value, LY_NSYIN)) {
332 /* extension */
333 c_ext++;
334 } else if (!strcmp(node->name, "base")) {
Radek Krejci018f1f52016-08-03 16:01:20 +0200335 if (c_base && (module->version < 2)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100336 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci18a44882017-01-23 13:47:29 +0100337 goto error;
338 }
Radek Krejci8d6b7422017-02-03 14:42:13 +0100339 if (lyp_yin_parse_subnode_ext(module, ident, LYEXT_PAR_IDENT, node, LYEXT_SUBSTMT_BASE, c_base, unres)) {
Radek Krejci18a44882017-01-23 13:47:29 +0100340 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200341 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200342 c_base++;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100343
Radek Krejci018f1f52016-08-03 16:01:20 +0200344 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
345 c_ftrs++;
346
347 } else {
348 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
Radek Krejci18a44882017-01-23 13:47:29 +0100349 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200350 }
351 }
352
353 if (c_base) {
354 ident->base_size = 0;
355 ident->base = calloc(c_base, sizeof *ident->base);
356 if (!ident->base) {
357 LOGMEM;
Radek Krejci18a44882017-01-23 13:47:29 +0100358 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200359 }
360 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200361 if (c_ftrs) {
362 ident->iffeature = calloc(c_ftrs, sizeof *ident->iffeature);
363 if (!ident->iffeature) {
364 LOGMEM;
Radek Krejci18a44882017-01-23 13:47:29 +0100365 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200366 }
367 }
Radek Krejcie534c132016-11-23 13:32:31 +0100368 if (c_ext) {
Radek Krejci18a44882017-01-23 13:47:29 +0100369 /* some extensions may be already present from the substatements */
370 reallocated = realloc(ident->ext, (c_ext + ident->ext_size) * sizeof *ident->ext);
371 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +0100372 LOGMEM;
Radek Krejci18a44882017-01-23 13:47:29 +0100373 goto error;
Radek Krejcie534c132016-11-23 13:32:31 +0100374 }
Radek Krejci18a44882017-01-23 13:47:29 +0100375 ident->ext = reallocated;
376
377 /* init memory */
378 memset(&ident->ext[ident->ext_size], 0, c_ext * sizeof *ident->ext);
Radek Krejcie534c132016-11-23 13:32:31 +0100379 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200380
Radek Krejcie534c132016-11-23 13:32:31 +0100381 LY_TREE_FOR_SAFE(yin->child, next, node) {
382 if (strcmp(node->ns->value, LY_NSYIN)) {
383 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +0100384 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 +0100385 ident->ext_size++;
386 if (rc) {
387 goto error;
388 }
389 } else if (!strcmp(node->name, "base")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200390 GETVAL(value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100391 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100392 if (!value) {
Radek Krejci18a44882017-01-23 13:47:29 +0100393 goto error;
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200394 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100395
Radek Krejci48464ed2016-03-17 15:44:09 +0100396 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vaskoc94283a2015-10-29 09:07:20 +0100397 lydict_remove(module->ctx, value);
Radek Krejci18a44882017-01-23 13:47:29 +0100398 goto error;
Michal Vaskoc94283a2015-10-29 09:07:20 +0100399 }
400 lydict_remove(module->ctx, value);
Radek Krejci018f1f52016-08-03 16:01:20 +0200401 } else if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200402 rc = fill_yin_iffeature((struct lys_node *)ident, 0, node, &ident->iffeature[ident->iffeature_size], unres);
Radek Krejci018f1f52016-08-03 16:01:20 +0200403 ident->iffeature_size++;
404 if (rc) {
Radek Krejci18a44882017-01-23 13:47:29 +0100405 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200406 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200407 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200408 }
Radek Krejci04581c62015-05-22 21:24:00 +0200409
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200410 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200411
412error:
413 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200414}
415
Michal Vasko0d343d12015-08-24 14:57:36 +0200416/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200417static int
Radek Krejciaa9c5202017-02-15 16:10:14 +0100418read_restr_substmt(struct lys_module *module, struct lys_restr *restr, struct lyxml_elem *yin,
Radek Krejcifccd1442017-01-16 10:26:57 +0100419 struct unres_schema *unres)
Radek Krejci41726f92015-06-19 13:11:05 +0200420{
Radek Krejcifccd1442017-01-16 10:26:57 +0100421 struct lyxml_elem *child, *next;
Radek Krejci461d1622015-06-30 14:06:28 +0200422 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200423
Radek Krejcifccd1442017-01-16 10:26:57 +0100424 LY_TREE_FOR_SAFE(yin->child, next, child) {
425 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200426 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200427 continue;
Radek Krejcifccd1442017-01-16 10:26:57 +0100428 } else if (strcmp(child->ns->value, LY_NSYIN)) {
429 /* extension */
Radek Krejciaa9c5202017-02-15 16:10:14 +0100430 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100431 return EXIT_FAILURE;
432 }
433 } else if (!strcmp(child->name, "description")) {
Radek Krejci41726f92015-06-19 13:11:05 +0200434 if (restr->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100435 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200436 return EXIT_FAILURE;
437 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100438 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100439 return EXIT_FAILURE;
440 }
441 restr->dsc = read_yin_subnode(module->ctx, child, "text");
Radek Krejci41726f92015-06-19 13:11:05 +0200442 if (!restr->dsc) {
443 return EXIT_FAILURE;
444 }
445 } else if (!strcmp(child->name, "reference")) {
446 if (restr->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100447 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200448 return EXIT_FAILURE;
449 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100450 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100451 return EXIT_FAILURE;
452 }
453 restr->ref = read_yin_subnode(module->ctx, child, "text");
Radek Krejci41726f92015-06-19 13:11:05 +0200454 if (!restr->ref) {
455 return EXIT_FAILURE;
456 }
457 } else if (!strcmp(child->name, "error-app-tag")) {
458 if (restr->eapptag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100459 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200460 return EXIT_FAILURE;
461 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100462 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_ERRTAG, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100463 return EXIT_FAILURE;
464 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200465 GETVAL(value, child, "value");
Radek Krejcifccd1442017-01-16 10:26:57 +0100466 restr->eapptag = lydict_insert(module->ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200467 } else if (!strcmp(child->name, "error-message")) {
468 if (restr->emsg) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100469 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200470 return EXIT_FAILURE;
471 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100472 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_ERRMSG, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100473 return EXIT_FAILURE;
474 }
475 restr->emsg = read_yin_subnode(module->ctx, child, "value");
Radek Krejci41726f92015-06-19 13:11:05 +0200476 if (!restr->emsg) {
477 return EXIT_FAILURE;
478 }
479 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100480 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200481 return EXIT_FAILURE;
482 }
Radek Krejci41726f92015-06-19 13:11:05 +0200483 }
484
485 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200486
487error:
488 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200489}
490
Michal Vasko88c29542015-11-27 14:57:53 +0100491/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
492int
Radek Krejcib8048692015-08-05 13:36:34 +0200493fill_yin_type(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_type *type,
Radek Krejci8d6b7422017-02-03 14:42:13 +0100494 int parenttype, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200495{
Michal Vasko0aee5c12016-06-17 14:27:26 +0200496 const char *value, *name;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200497 struct lys_node *siter;
Radek Krejcie534c132016-11-23 13:32:31 +0100498 struct lyxml_elem *next, *next2, *node, *child, exts;
Radek Krejcifccd1442017-01-16 10:26:57 +0100499 struct lys_restr **restrs, *restr;
Radek Krejci1c5890d2016-08-02 13:15:42 +0200500 struct lys_type_bit bit, *bits_sc = NULL;
501 struct lys_type_enum *enms_sc = NULL; /* shortcut */
Radek Krejcie663e012016-08-01 17:12:34 +0200502 struct lys_type *dertype;
Radek Krejcie534c132016-11-23 13:32:31 +0100503 int i, j, rc, val_set, c_ftrs, c_ext = 0;
Radek Krejcidc008d72016-02-17 13:12:14 +0100504 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200505 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200506 int64_t p, p_;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200507 size_t len;
508 char *buf, modifier;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200509
Radek Krejcie534c132016-11-23 13:32:31 +0100510 /* init */
511 memset(&exts, 0, sizeof exts);
512
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200513 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100514 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200515 if (!value) {
516 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200517 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200518
519 i = parse_identifier(value);
520 if (i < 1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100521 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100522 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200523 goto error;
524 }
525 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100526 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200527 if (value[i]) {
528 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100529 name += i;
530 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100531 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100532 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200533 goto error;
534 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200535 /* name is in dictionary, but moved */
Radek Krejci225376f2016-02-16 17:36:22 +0100536 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200537 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200538
Radek Krejci225376f2016-02-16 17:36:22 +0100539 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200540 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100541 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200542 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200543 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100544
545 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200546 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200547 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200548 lydict_remove(module->ctx, value);
Radek Krejcidc008d72016-02-17 13:12:14 +0100549 ret = EXIT_FAILURE;
550 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200551 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200552 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200553
Radek Krejci9b6aad22016-09-20 15:55:51 +0200554 if (type->base == LY_TYPE_ERR) {
Radek Krejcic13db382016-08-16 10:52:42 +0200555 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Radek Krejci9b6aad22016-09-20 15:55:51 +0200556 * 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 +0200557 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
558 if (siter) {
Radek Krejci6ff885d2017-01-03 14:06:22 +0100559#if __BYTE_ORDER == __LITTLE_ENDIAN
560 if (!((uint8_t*)&((struct lys_node_grp *)siter)->flags)[1]) {
Radek Krejcic13db382016-08-16 10:52:42 +0200561 LOGINT;
562 goto error;
563 }
Radek Krejci6ff885d2017-01-03 14:06:22 +0100564 ((uint8_t*)&((struct lys_node_grp *)siter)->flags)[1]--;
565#else
566 if (!((uint8_t*)&((struct lys_node_grp *)siter)->flags)[0]) {
567 LOGINT;
568 goto error;
569 }
570 ((uint8_t*)&((struct lys_node_grp *)siter)->flags)[0]--;
571#endif
Radek Krejcic13db382016-08-16 10:52:42 +0200572 } else {
573 LOGINT;
574 goto error;
575 }
576 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200577 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200578
Radek Krejcicf509982015-12-15 09:22:44 +0100579 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100580 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejci48464ed2016-03-17 15:44:09 +0100581 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100582 return -1;
583 }
584
Radek Krejcie534c132016-11-23 13:32:31 +0100585 /* parse extension instances */
586 LY_TREE_FOR_SAFE(yin->child, next, node) {
587 if (!node->ns) {
588 /* garbage */
589 lyxml_free(module->ctx, node);
590 continue;
591 } else if (!strcmp(node->ns->value, LY_NSYIN)) {
592 /* YANG (YIN) statements - process later */
593 continue;
594 }
595
596 lyxml_unlink_elem(module->ctx, node, 2);
597 lyxml_add_child(module->ctx, &exts, node);
598 c_ext++;
599 }
600 if (c_ext) {
601 type->ext = calloc(c_ext, sizeof *type->ext);
602 if (!type->ext) {
603 LOGMEM;
604 goto error;
605 }
606 LY_TREE_FOR_SAFE(exts.child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +0100607 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 +0100608 type->ext_size++;
609 if (rc) {
610 goto error;
611 }
612 }
613 }
614
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200615 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200616 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200617 /* RFC 6020 9.7.4 - bit */
618
619 /* get bit specifications, at least one must be present */
620 LY_TREE_FOR_SAFE(yin->child, next, node) {
621 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200622 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200623 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100624 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200625 type->info.bits.count = 0;
Radek Krejci41726f92015-06-19 13:11:05 +0200626 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200627 }
628 }
Radek Krejcie663e012016-08-01 17:12:34 +0200629 dertype = &type->der->type;
630 if (!dertype->der) {
631 if (!type->info.bits.count) {
632 /* type is derived directly from buit-in bits type and bit statement is required */
633 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
634 goto error;
635 }
636 } else {
637 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
638 if (module->version < 2 && type->info.bits.count) {
639 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
640 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
641 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejci69794c62016-08-02 11:01:21 +0200642 type->info.bits.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200643 goto error;
644 }
Radek Krejciac781922015-07-09 15:35:14 +0200645 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200646
647 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100648 if (!type->info.bits.bit) {
649 LOGMEM;
650 goto error;
651 }
Radek Krejci73adb602015-07-02 18:07:40 +0200652 p = 0;
653 i = -1;
654 LY_TREE_FOR(yin->child, next) {
655 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200656 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200657
658 GETVAL(value, next, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100659 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100660 goto error;
661 }
662
Radek Krejci994b6f62015-06-18 16:47:27 +0200663 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100664 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 +0200665 type->info.bits.count = i + 1;
666 goto error;
667 }
668
Radek Krejcie663e012016-08-01 17:12:34 +0200669 if (!dertype->der) { /* directly derived type from bits built-in type */
670 /* check the name uniqueness */
671 for (j = 0; j < i; j++) {
672 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
673 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
674 type->info.bits.count = i + 1;
675 goto error;
676 }
677 }
678 } else {
679 /* restricted bits type - the name MUST be used in the base type */
680 bits_sc = dertype->info.bits.bit;
681 for (j = 0; j < dertype->info.bits.count; j++) {
682 if (ly_strequal(bits_sc[j].name, value, 1)) {
683 break;
684 }
685 }
686 if (j == dertype->info.bits.count) {
687 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci994b6f62015-06-18 16:47:27 +0200688 type->info.bits.count = i + 1;
689 goto error;
690 }
691 }
692
Radek Krejcie663e012016-08-01 17:12:34 +0200693
Radek Krejci0d70c372015-07-02 16:23:10 +0200694 p_ = -1;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100695 LY_TREE_FOR_SAFE(next->child, next2, node) {
696 if (!node->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200697 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200698 continue;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100699 } else if (strcmp(node->ns->value, LY_NSYIN)) {
700 /* extension */
Radek Krejci8d6b7422017-02-03 14:42:13 +0100701 if (lyp_yin_parse_subnode_ext(module, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +0100702 LYEXT_SUBSTMT_SELF, 0, unres)) {
703 goto error;
704 }
705 } else if (!strcmp(node->name, "position")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200706 if (p_ != -1) {
707 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
708 type->info.bits.count = i + 1;
709 goto error;
710 }
711
Radek Krejci0d70c372015-07-02 16:23:10 +0200712 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200713 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200714
715 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200716 if (p_ < 0 || p_ > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100717 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200718 type->info.bits.count = i + 1;
719 goto error;
720 }
721 type->info.bits.bit[i].pos = (uint32_t)p_;
722
Radek Krejcie663e012016-08-01 17:12:34 +0200723 if (!dertype->der) { /* directly derived type from bits built-in type */
724 /* keep the highest enum value for automatic increment */
725 if (type->info.bits.bit[i].pos >= p) {
726 p = type->info.bits.bit[i].pos;
727 p++;
728 } else {
729 /* check that the value is unique */
730 for (j = 0; j < i; j++) {
731 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
732 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
733 type->info.bits.bit[i].pos, type->info.bits.bit[i].name,
734 type->info.bits.bit[j].name);
735 type->info.bits.count = i + 1;
736 goto error;
737 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200738 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200739 }
740 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200741
Radek Krejci8d6b7422017-02-03 14:42:13 +0100742 if (lyp_yin_parse_subnode_ext(module, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +0100743 LYEXT_SUBSTMT_POSITION, 0, unres)) {
744 goto error;
745 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200746 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
747 c_ftrs++;
Radek Krejci0d70c372015-07-02 16:23:10 +0200748 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100749 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200750 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200751 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200752 }
Radek Krejcie663e012016-08-01 17:12:34 +0200753
754 if (!dertype->der) { /* directly derived type from bits built-in type */
755 if (p_ == -1) {
756 /* assign value automatically */
757 if (p > UINT32_MAX) {
758 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
759 type->info.bits.count = i + 1;
760 goto error;
761 }
762 type->info.bits.bit[i].pos = (uint32_t)p;
763 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
764 p++;
Radek Krejci994b6f62015-06-18 16:47:27 +0200765 }
Radek Krejcie663e012016-08-01 17:12:34 +0200766 } else { /* restricted bits type */
767 if (p_ == -1) {
768 /* automatically assign position from base type */
769 type->info.bits.bit[i].pos = bits_sc[j].pos;
770 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
771 } else {
772 /* check that the assigned position corresponds to the original
773 * position of the bit in the base type */
774 if (p_ != bits_sc[j].pos) {
775 /* p_ - assigned position in restricted bits
776 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
777 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
Radek Krejci541a45d2016-08-02 13:12:07 +0200778 type->info.bits.bit[i].name, bits_sc[j].pos);
Radek Krejcie663e012016-08-01 17:12:34 +0200779 type->info.bits.count = i + 1;
780 goto error;
781 }
782 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200783 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200784
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200785 /* if-features */
786 if (c_ftrs) {
787 bits_sc = &type->info.bits.bit[i];
788 bits_sc->iffeature = calloc(c_ftrs, sizeof *bits_sc->iffeature);
789 if (!bits_sc->iffeature) {
790 LOGMEM;
Radek Krejci994b6f62015-06-18 16:47:27 +0200791 type->info.bits.count = i + 1;
792 goto error;
793 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200794
795 LY_TREE_FOR(next->child, node) {
796 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200797 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200798 &bits_sc->iffeature[bits_sc->iffeature_size], unres);
799 bits_sc->iffeature_size++;
800 if (rc) {
801 type->info.bits.count = i + 1;
802 goto error;
803 }
804 }
805 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200806 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200807
808 /* keep them ordered by position */
809 j = i;
810 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
811 /* switch them */
812 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
813 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
814 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
815 j--;
816 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200817 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200818 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200819
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200820 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200821 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200822 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200823
Radek Krejcif9401c32015-06-26 16:47:36 +0200824 if (!strcmp(node->name, "range")) {
825 if (type->info.dec64.range) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100826 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200827 goto error;
828 }
829
830 GETVAL(value, node, "value");
Radek Krejcif9401c32015-06-26 16:47:36 +0200831 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100832 if (!type->info.dec64.range) {
833 LOGMEM;
834 goto error;
835 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200836 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
837
838 /* get possible substatements */
Radek Krejciaa9c5202017-02-15 16:10:14 +0100839 if (read_restr_substmt(module, type->info.dec64.range, node, unres)) {
Radek Krejcif9401c32015-06-26 16:47:36 +0200840 goto error;
841 }
842 } else if (!strcmp(node->name, "fraction-digits")) {
843 if (type->info.dec64.dig) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100844 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200845 goto error;
846 }
847 GETVAL(value, node, "value");
848 v = strtol(value, NULL, 10);
849
850 /* range check */
851 if (v < 1 || v > 18) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100852 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200853 goto error;
854 }
855 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200856 type->info.dec64.div = 10;
857 for (i = 1; i < v; i++) {
858 type->info.dec64.div *= 10;
859 }
Radek Krejci47f7ea52017-01-23 13:14:09 +0100860
861 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +0100862 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_DIGITS, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +0100863 goto error;
864 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200865 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100866 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200867 goto error;
868 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200869 }
870
871 /* mandatory sub-statement(s) check */
872 if (!type->info.dec64.dig && !type->der->type.der) {
873 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejci48464ed2016-03-17 15:44:09 +0100874 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200875 goto error;
876 }
Radek Krejci7511f402015-07-10 09:56:30 +0200877 if (type->info.dec64.dig && type->der->type.der) {
878 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100879 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200880 goto error;
881 }
Radek Krejci4800f652016-09-08 14:02:52 +0200882
883 /* copy fraction-digits specification from parent type for easier internal use */
884 if (type->der->type.der) {
885 type->info.dec64.dig = type->der->type.info.dec64.dig;
886 type->info.dec64.div = type->der->type.info.dec64.div;
887 }
888
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200889 if (type->info.dec64.range && lyp_check_length_range(type->info.dec64.range->expr, type)) {
890 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
891 goto error;
892 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200893 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200894
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200895 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200896 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200897
Radek Krejci994b6f62015-06-18 16:47:27 +0200898 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200899 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200900
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200901 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200902 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200903 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100904 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200905 type->info.enums.count = 0;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200906 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200907 }
908 }
Radek Krejcie663e012016-08-01 17:12:34 +0200909 dertype = &type->der->type;
910 if (!dertype->der) {
911 if (!type->info.enums.count) {
912 /* type is derived directly from buit-in enumeartion type and enum statement is required */
913 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
914 goto error;
915 }
916 } else {
917 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
918 if (module->version < 2 && type->info.enums.count) {
919 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
920 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
921 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejci69794c62016-08-02 11:01:21 +0200922 type->info.enums.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200923 goto error;
924 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200925 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200926
Radek Krejci1574a8d2015-08-03 14:16:52 +0200927 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100928 if (!type->info.enums.enm) {
929 LOGMEM;
930 goto error;
931 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200932
Radek Krejcie663e012016-08-01 17:12:34 +0200933 v = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200934 i = -1;
935 LY_TREE_FOR(yin->child, next) {
936 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200937 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200938
939 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100940 if (!value[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100941 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
942 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100943 goto error;
944 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200945 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100946 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 +0200947 type->info.enums.count = i + 1;
948 goto error;
949 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200950
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200951 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200952 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200953 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100954 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200955 type->info.enums.count = i + 1;
956 goto error;
957 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200958
Radek Krejcie663e012016-08-01 17:12:34 +0200959 if (!dertype->der) { /* directly derived type from enumeration built-in type */
960 /* check the name uniqueness */
961 for (j = 0; j < i; j++) {
962 if (ly_strequal(type->info.enums.enm[j].name, value, 1)) {
963 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, value);
964 type->info.enums.count = i + 1;
965 goto error;
966 }
967 }
968 } else {
969 /* restricted enumeration type - the name MUST be used in the base type */
970 enms_sc = dertype->info.enums.enm;
971 for (j = 0; j < dertype->info.enums.count; j++) {
972 if (ly_strequal(enms_sc[j].name, value, 1)) {
973 break;
974 }
975 }
976 if (j == dertype->info.enums.count) {
977 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200978 type->info.enums.count = i + 1;
979 goto error;
980 }
981 }
Radek Krejci04581c62015-05-22 21:24:00 +0200982
Radek Krejcie663e012016-08-01 17:12:34 +0200983 val_set = 0;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100984 LY_TREE_FOR_SAFE(next->child, next2, node) {
985 if (!node->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200986 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200987 continue;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100988 } else if (strcmp(node->ns->value, LY_NSYIN)) {
989 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +0100990 if (lyp_yin_parse_subnode_ext(module, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +0100991 LYEXT_SUBSTMT_SELF, 0, unres)) {
992 goto error;
993 }
994 } else if (!strcmp(node->name, "value")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200995 if (val_set) {
996 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
997 type->info.enums.count = i + 1;
998 goto error;
999 }
1000
Radek Krejci0d70c372015-07-02 16:23:10 +02001001 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +02001002 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +02001003
1004 /* range check */
1005 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001006 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +02001007 type->info.enums.count = i + 1;
1008 goto error;
1009 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001010 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +02001011
Radek Krejcie663e012016-08-01 17:12:34 +02001012 if (!dertype->der) { /* directly derived type from enumeration built-in type */
Pavol Vican5de389c2016-08-30 08:55:15 +02001013 if (!i) {
1014 /* change value, which is assigned automatically, if first enum has value. */
Radek Krejcie663e012016-08-01 17:12:34 +02001015 v = type->info.enums.enm[i].value;
1016 v++;
1017 } else {
Pavol Vican5de389c2016-08-30 08:55:15 +02001018 /* keep the highest enum value for automatic increment */
1019 if (type->info.enums.enm[i].value >= v) {
1020 v = type->info.enums.enm[i].value;
1021 v++;
1022 } else {
1023 /* check that the value is unique */
1024 for (j = 0; j < i; j++) {
1025 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
1026 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
1027 type->info.enums.enm[i].value, type->info.enums.enm[i].name,
1028 type->info.enums.enm[j].name);
1029 type->info.enums.count = i + 1;
1030 goto error;
1031 }
Radek Krejcie663e012016-08-01 17:12:34 +02001032 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001033 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001034 }
1035 }
Radek Krejcifc8d8322016-06-24 11:23:23 +02001036 val_set = 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001037
Radek Krejci8d6b7422017-02-03 14:42:13 +01001038 if (lyp_yin_parse_subnode_ext(module, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +01001039 LYEXT_SUBSTMT_VALUE, 0, unres)) {
1040 goto error;
1041 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001042 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
1043 c_ftrs++;
1044
Radek Krejci0d70c372015-07-02 16:23:10 +02001045 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001046 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001047 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001048 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001049 }
Radek Krejcie663e012016-08-01 17:12:34 +02001050
1051 if (!dertype->der) { /* directly derived type from enumeration */
1052 if (!val_set) {
1053 /* assign value automatically */
1054 if (v > INT32_MAX) {
1055 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
1056 type->info.enums.count = i + 1;
1057 goto error;
1058 }
1059 type->info.enums.enm[i].value = v;
1060 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1061 v++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001062 }
Radek Krejcie663e012016-08-01 17:12:34 +02001063 } else { /* restricted enum type */
1064 if (!val_set) {
1065 /* automatically assign value from base type */
1066 type->info.enums.enm[i].value = enms_sc[j].value;
1067 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1068 } else {
1069 /* check that the assigned value corresponds to the original
1070 * value of the enum in the base type */
1071 if (v_ != enms_sc[j].value) {
1072 /* v_ - assigned value in restricted enum
1073 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
1074 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL,
Radek Krejci541a45d2016-08-02 13:12:07 +02001075 type->info.enums.enm[i].value, type->info.enums.enm[i].name, enms_sc[j].value);
Radek Krejcie663e012016-08-01 17:12:34 +02001076 type->info.enums.count = i + 1;
1077 goto error;
1078 }
1079 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001080 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001081
1082 /* if-features */
1083 if (c_ftrs) {
1084 enms_sc = &type->info.enums.enm[i];
1085 enms_sc->iffeature = calloc(c_ftrs, sizeof *enms_sc->iffeature);
1086 if (!enms_sc->iffeature) {
1087 LOGMEM;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001088 type->info.enums.count = i + 1;
1089 goto error;
1090 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001091
1092 LY_TREE_FOR(next->child, node) {
1093 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02001094 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001095 &enms_sc->iffeature[enms_sc->iffeature_size], unres);
1096 enms_sc->iffeature_size++;
1097 if (rc) {
1098 type->info.enums.count = i + 1;
1099 goto error;
1100 }
1101 }
1102 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001103 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001104
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001105 }
1106 break;
1107
1108 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +02001109 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001110
Michal Vaskof2d43962016-09-02 11:10:16 +02001111 /* get base specification, at least one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +02001112 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001113
Michal Vaskoe29c6622015-11-27 15:02:31 +01001114 if (strcmp(node->name, "base")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001115 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001116 goto error;
1117 }
Michal Vaskof2d43962016-09-02 11:10:16 +02001118
1119 GETVAL(value, yin->child, "name");
1120 /* store in the JSON format */
1121 value = transform_schema2json(module, value);
1122 if (!value) {
1123 goto error;
1124 }
1125 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
1126 lydict_remove(module->ctx, value);
Michal Vaskof2d43962016-09-02 11:10:16 +02001127 if (rc == -1) {
1128 goto error;
1129 }
Radek Krejci18a44882017-01-23 13:47:29 +01001130
Radek Krejci8d6b7422017-02-03 14:42:13 +01001131 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_BASE, 0, unres)) {
Radek Krejci18a44882017-01-23 13:47:29 +01001132 goto error;
1133 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001134 }
1135
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001136 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +02001137 if (type->der->type.der) {
Michal Vaskof2d43962016-09-02 11:10:16 +02001138 /* this is just a derived type with no base required */
Radek Krejci65c889c2015-06-22 10:17:22 +02001139 break;
1140 }
Radek Krejci48464ed2016-03-17 15:44:09 +01001141 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001142 goto error;
Pavol Vicanf0046f42016-09-07 15:11:09 +02001143 } else {
1144 if (type->der->type.der) {
1145 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
1146 goto error;
1147 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001148 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001149 if (yin->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001150 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001151 goto error;
1152 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001153 break;
1154
1155 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +02001156 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +02001157 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001158
Radek Krejciaf351422015-06-19 14:49:38 +02001159 if (!strcmp(node->name, "require-instance")) {
1160 if (type->info.inst.req) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001161 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001162 goto error;
1163 }
1164 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001165 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001166 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001167 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001168 type->info.inst.req = -1;
1169 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001170 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001171 goto error;
1172 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001173
1174 /* extensions */
Radek Krejcibe336392017-02-07 10:54:24 +01001175 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINSTANCE, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001176 goto error;
1177 }
Radek Krejciaf351422015-06-19 14:49:38 +02001178 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001179 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001180 goto error;
1181 }
Radek Krejciaf351422015-06-19 14:49:38 +02001182 }
Michal Vasko8548cf92015-07-20 15:17:53 +02001183
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001184 break;
1185
Radek Krejcif2860132015-06-20 12:37:20 +02001186 case LY_TYPE_BINARY:
1187 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001188 case LY_TYPE_INT8:
1189 case LY_TYPE_INT16:
1190 case LY_TYPE_INT32:
1191 case LY_TYPE_INT64:
1192 case LY_TYPE_UINT8:
1193 case LY_TYPE_UINT16:
1194 case LY_TYPE_UINT32:
1195 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +02001196 /* RFC 6020 9.2.4 - range */
1197
1198 /* length and range are actually the same restriction, so process
1199 * them by this common code, we just need to differ the name and
1200 * structure where the information will be stored
1201 */
1202 if (type->base == LY_TYPE_BINARY) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001203 restrs = &type->info.binary.length;
Radek Krejcif2860132015-06-20 12:37:20 +02001204 name = "length";
1205 } else {
Radek Krejcifccd1442017-01-16 10:26:57 +01001206 restrs = &type->info.num.range;
Radek Krejcif2860132015-06-20 12:37:20 +02001207 name = "range";
1208 }
1209
Radek Krejci73adb602015-07-02 18:07:40 +02001210 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001211
Radek Krejcif2860132015-06-20 12:37:20 +02001212 if (!strcmp(node->name, name)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001213 if (*restrs) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001214 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001215 goto error;
1216 }
1217
1218 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +02001219 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001220 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +02001221 goto error;
1222 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001223 *restrs = calloc(1, sizeof **restrs);
1224 if (!(*restrs)) {
Michal Vasko253035f2015-12-17 16:58:13 +01001225 LOGMEM;
1226 goto error;
1227 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001228 (*restrs)->expr = lydict_insert(module->ctx, value, 0);
Radek Krejcif2860132015-06-20 12:37:20 +02001229
1230 /* get possible substatements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001231 if (read_restr_substmt(module, *restrs, node, unres)) {
Radek Krejcif2860132015-06-20 12:37:20 +02001232 goto error;
1233 }
1234 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001235 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001236 goto error;
1237 }
Radek Krejcif2860132015-06-20 12:37:20 +02001238 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001239 break;
1240
1241 case LY_TYPE_LEAFREF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02001242 /* flag resolving for later use */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001243 if (!parenttype) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001244 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
1245 if (siter) {
1246 /* just a flag - do not resolve */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001247 parenttype = 1;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001248 }
1249 }
1250
Radek Krejcidc4c1412015-06-19 15:39:54 +02001251 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +02001252 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001253
Michal Vasko88c29542015-11-27 14:57:53 +01001254 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +02001255 if (type->info.lref.path) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001256 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001257 goto error;
1258 }
1259
1260 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +02001261 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +01001262 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +02001263 if (!type->info.lref.path) {
1264 goto error;
1265 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001266
1267 /* try to resolve leafref path only when this is instantiated
1268 * leaf, so it is not:
1269 * - typedef's type,
1270 * - in grouping definition,
1271 * - just instantiated in a grouping definition,
1272 * because in those cases the nodes referenced in path might not be present
1273 * and it is not a bug. */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001274 if (!parenttype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001275 goto error;
1276 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001277
1278 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001279 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_PATH, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001280 goto error;
1281 }
Radek Krejcid6353ed2016-09-15 13:30:45 +02001282 } else if (module->version >= 2 && !strcmp(node->name, "require-instance")) {
Michal Vasko08ae53e2016-09-02 12:40:04 +02001283 if (type->info.lref.req) {
1284 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
1285 goto error;
1286 }
1287 GETVAL(value, node, "value");
1288 if (!strcmp(value, "true")) {
1289 type->info.lref.req = 1;
1290 } else if (!strcmp(value, "false")) {
1291 type->info.lref.req = -1;
1292 } else {
1293 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
1294 goto error;
1295 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001296
1297 /* extensions */
Radek Krejcibe336392017-02-07 10:54:24 +01001298 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINSTANCE, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001299 goto error;
1300 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001301 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001302 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001303 goto error;
1304 }
Radek Krejci73adb602015-07-02 18:07:40 +02001305 }
1306
Radek Krejci742be352016-07-17 12:18:54 +02001307 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001308 if (!type->der->type.der) {
1309 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
1310 goto error;
1311 } else {
1312 /* copy leafref definition into the derived type */
1313 type->info.lref.path = lydict_insert(module->ctx, type->der->type.info.lref.path, 0);
1314 /* and resolve the path at the place we are (if not in grouping/typedef) */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001315 if (!parenttype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001316 goto error;
1317 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001318 }
Radek Krejci742be352016-07-17 12:18:54 +02001319 }
1320
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001321 break;
1322
1323 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +02001324 /* RFC 6020 9.4.4 - length */
1325 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +02001326 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +02001327 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001328
Radek Krejci3733a802015-06-19 13:43:21 +02001329 if (!strcmp(node->name, "length")) {
1330 if (type->info.str.length) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001331 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001332 goto error;
1333 }
1334
1335 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +02001336 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001337 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +02001338 goto error;
1339 }
1340 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +01001341 if (!type->info.str.length) {
1342 LOGMEM;
1343 goto error;
1344 }
Radek Krejci3733a802015-06-19 13:43:21 +02001345 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
1346
Radek Krejci5fbc9162015-06-19 14:11:11 +02001347 /* get possible sub-statements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001348 if (read_restr_substmt(module, type->info.str.length, node, unres)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001349 goto error;
1350 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001351 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001352 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +02001353 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001354 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001355 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001356 goto error;
1357 }
1358 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001359 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001360 if (i) {
1361 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +01001362 if (!type->info.str.patterns) {
1363 LOGMEM;
1364 goto error;
1365 }
Radek Krejci73adb602015-07-02 18:07:40 +02001366 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +01001367 GETVAL(value, node, "value");
Michal Vasko0aee5c12016-06-17 14:27:26 +02001368 if (lyp_check_pattern(value, NULL)) {
Michal Vasko69068852015-07-13 14:34:31 +02001369 free(type->info.str.patterns);
Radek Krejci9f1e8532016-06-16 11:18:21 +02001370 type->info.str.patterns = NULL;
Michal Vasko69068852015-07-13 14:34:31 +02001371 goto error;
1372 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001373 restr = &type->info.str.patterns[type->info.str.pat_count]; /* shortcut */
Michal Vasko69068852015-07-13 14:34:31 +02001374
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001375 modifier = 0x06; /* ACK */
1376 name = NULL;
Radek Krejcifccd1442017-01-16 10:26:57 +01001377 if (module->version >= 2) {
1378 LY_TREE_FOR_SAFE(node->child, next2, child) {
1379 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
1380 if (name) {
1381 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
1382 goto error;
1383 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001384
Radek Krejcifccd1442017-01-16 10:26:57 +01001385 GETVAL(name, child, "value");
1386 if (!strcmp(name, "invert-match")) {
1387 modifier = 0x15; /* NACK */
1388 } else {
1389 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
1390 goto error;
1391 }
1392 /* get extensions of the modifier */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001393 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child,
Radek Krejciaa9c5202017-02-15 16:10:14 +01001394 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
1395 goto error;
Radek Krejcifccd1442017-01-16 10:26:57 +01001396 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001397
Radek Krejcifccd1442017-01-16 10:26:57 +01001398 lyxml_free(module->ctx, child);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001399 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001400 }
1401 }
1402
1403 len = strlen(value);
1404 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
1405 buf[0] = modifier;
1406 strcpy(&buf[1], value);
1407
Radek Krejcifccd1442017-01-16 10:26:57 +01001408 restr->expr = lydict_insert_zc(module->ctx, buf);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001409
1410 /* get possible sub-statements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001411 if (read_restr_substmt(module, restr, node, unres)) {
Michal Vasko69068852015-07-13 14:34:31 +02001412 free(type->info.str.patterns);
Pavol Vican9fc5d642016-08-30 15:23:19 +02001413 type->info.str.patterns = NULL;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001414 goto error;
1415 }
Radek Krejci73adb602015-07-02 18:07:40 +02001416 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001417 }
1418 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001419 break;
1420
1421 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001422 /* RFC 6020 7.4 - type */
1423 /* count number of types in union */
1424 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001425 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001426
Radek Krejcie4c366b2015-07-02 10:11:31 +02001427 if (!strcmp(node->name, "type")) {
Radek Krejci038d5d92016-09-12 15:07:15 +02001428 if (type->der->type.der) {
1429 /* type can be a substatement only in "union" type, not in derived types */
1430 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "derived type");
1431 goto error;
1432 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001433 i++;
1434 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001435 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001436 goto error;
1437 }
1438 }
1439
Radek Krejci038d5d92016-09-12 15:07:15 +02001440 if (!i && !type->der->type.der) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001441 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001442 goto error;
1443 }
1444
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001445 /* inherit instid presence information */
1446 if ((type->der->type.base == LY_TYPE_UNION) && type->der->type.info.uni.has_ptr_type) {
1447 type->info.uni.has_ptr_type = 1;
1448 }
1449
Radek Krejcie4c366b2015-07-02 10:11:31 +02001450 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001451 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +01001452 if (!type->info.uni.types) {
1453 LOGMEM;
1454 goto error;
1455 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001456 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001457 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +01001458 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001459 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], parenttype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +01001460 if (!rc) {
1461 type->info.uni.count++;
1462
Radek Krejci7de36cf2016-09-12 16:18:50 +02001463 if (module->version < 2) {
1464 /* union's type cannot be empty or leafref */
1465 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
1466 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
1467 rc = -1;
1468 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
1469 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
1470 rc = -1;
1471 }
Michal Vasko88c29542015-11-27 14:57:53 +01001472 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001473
1474 if ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_INST)
1475 || (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF)) {
1476 type->info.uni.has_ptr_type = 1;
1477 }
Michal Vasko88c29542015-11-27 14:57:53 +01001478 }
1479 if (rc) {
1480 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
1481 for (i = 0; i < type->info.uni.count; ++i) {
1482 lys_type_free(module->ctx, &type->info.uni.types[i]);
1483 }
1484 free(type->info.uni.types);
1485 type->info.uni.types = NULL;
1486 type->info.uni.count = 0;
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001487 type->info.uni.has_ptr_type = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +02001488 type->der = NULL;
1489 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +01001490
1491 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +01001492 ret = EXIT_FAILURE;
Michal Vasko88c29542015-11-27 14:57:53 +01001493 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001494 goto error;
1495 }
Michal Vasko88c29542015-11-27 14:57:53 +01001496 }
1497 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001498
Michal Vasko88c29542015-11-27 14:57:53 +01001499 case LY_TYPE_BOOL:
1500 case LY_TYPE_EMPTY:
1501 /* no sub-statement allowed */
Radek Krejcie534c132016-11-23 13:32:31 +01001502 if (yin->child) {
1503 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->child->name);
1504 goto error;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001505 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001506 break;
1507
1508 default:
Michal Vasko88c29542015-11-27 14:57:53 +01001509 LOGINT;
1510 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001511 }
1512
1513 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001514
1515error:
Radek Krejcidc008d72016-02-17 13:12:14 +01001516 if (type->module_name) {
1517 lydict_remove(module->ctx, type->module_name);
1518 type->module_name = NULL;
1519 }
Radek Krejcie534c132016-11-23 13:32:31 +01001520 lyxml_free_withsiblings(module->ctx, exts.child);
1521
Radek Krejcidc008d72016-02-17 13:12:14 +01001522 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001523}
1524
Michal Vasko0d343d12015-08-24 14:57:36 +02001525/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001526static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01001527fill_yin_typedef(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_tpdf *tpdf,
1528 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001529{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001530 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +01001531 struct lyxml_elem *node, *next;
Radek Krejcie534c132016-11-23 13:32:31 +01001532 int rc, has_type = 0, c_ext = 0;
Radek Krejci59a349f2017-01-24 10:14:31 +01001533 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001534
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001535 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001536 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001537 goto error;
1538 }
1539 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001540
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001541 /* generic part - status, description, reference */
Radek Krejci07d0fb92017-01-13 14:11:05 +01001542 if (read_yin_common(module, NULL, tpdf, LYEXT_PAR_TPDF, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001543 goto error;
1544 }
Radek Krejcieac35532015-05-31 19:09:15 +02001545
Michal Vasko88c29542015-11-27 14:57:53 +01001546 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejcie534c132016-11-23 13:32:31 +01001547 if (strcmp(node->ns->value, LY_NSYIN)) {
1548 /* extension */
1549 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02001550 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01001551 } else if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001552 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001553 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001554 goto error;
1555 }
Michal Vasko88c29542015-11-27 14:57:53 +01001556 /* HACK for unres */
1557 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001558 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001559 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001560 goto error;
1561 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001562 has_type = 1;
Radek Krejcie534c132016-11-23 13:32:31 +01001563
Radek Krejci07d0fb92017-01-13 14:11:05 +01001564 /* 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 +01001565 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001566 } else if (!strcmp(node->name, "default")) {
1567 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001568 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001569 goto error;
1570 }
1571 GETVAL(value, node, "value");
1572 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001573
Radek Krejci8d6b7422017-02-03 14:42:13 +01001574 if (lyp_yin_parse_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001575 goto error;
1576 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001577 } else if (!strcmp(node->name, "units")) {
1578 if (tpdf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001579 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001580 goto error;
1581 }
1582 GETVAL(value, node, "name");
1583 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001584
Radek Krejci8d6b7422017-02-03 14:42:13 +01001585 if (lyp_yin_parse_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001586 goto error;
1587 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001588 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001589 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001590 goto error;
1591 }
Radek Krejcie534c132016-11-23 13:32:31 +01001592
1593 lyxml_free(module->ctx, node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001594 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001595
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001596 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001597 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001598 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001599 goto error;
1600 }
Radek Krejcieac35532015-05-31 19:09:15 +02001601
Michal Vasko478c4652016-07-21 12:55:01 +02001602 /* check default value (if not defined, there still could be some restrictions
1603 * that need to be checked against a default value from a derived type) */
Radek Krejciab08f0f2017-03-09 16:37:15 +01001604 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPEDEF_DFLT, (struct lys_node *)(&tpdf->dflt)) == -1) {
Michal Vasko478c4652016-07-21 12:55:01 +02001605 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001606 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001607
Radek Krejcie534c132016-11-23 13:32:31 +01001608 /* finish extensions parsing */
1609 if (c_ext) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001610 /* some extensions may be already present from the substatements */
1611 reallocated = realloc(tpdf->ext, (c_ext + tpdf->ext_size) * sizeof *tpdf->ext);
1612 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01001613 LOGMEM;
1614 goto error;
1615 }
Radek Krejci59a349f2017-01-24 10:14:31 +01001616 tpdf->ext = reallocated;
1617
1618 /* init memory */
1619 memset(&tpdf->ext[tpdf->ext_size], 0, c_ext * sizeof *tpdf->ext);
1620
Radek Krejcie534c132016-11-23 13:32:31 +01001621 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001622 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 +01001623 tpdf->ext_size++;
1624 if (rc) {
1625 goto error;
1626 }
1627 }
1628 }
1629
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001630 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001631
1632error:
1633
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001634 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001635}
1636
Radek Krejcia1a6b762016-11-14 09:53:38 +09001637static int
Radek Krejcie534c132016-11-23 13:32:31 +01001638fill_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 +09001639{
1640 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01001641 struct lyxml_elem *child, *node, *next, *next2;
1642 int c_ext = 0, rc;
Radek Krejci1fb02182017-01-24 11:20:55 +01001643 void *reallocated;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001644
1645 GETVAL(value, yin, "name");
1646
1647 if (lyp_check_identifier(value, LY_IDENT_EXTENSION, module, NULL)) {
1648 goto error;
1649 }
1650 ext->name = lydict_insert(module->ctx, value, strlen(value));
1651
Radek Krejci07d0fb92017-01-13 14:11:05 +01001652 if (read_yin_common(module, NULL, ext, LYEXT_PAR_EXT, yin, OPT_MODULE, unres)) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09001653 goto error;
1654 }
1655
Radek Krejcie534c132016-11-23 13:32:31 +01001656 LY_TREE_FOR_SAFE(yin->child, next, node) {
1657 if (strcmp(node->ns->value, LY_NSYIN)) {
1658 /* possible extension instance */
1659 c_ext++;
1660 } else if (!strcmp(node->name, "argument")) {
1661 /* argument */
1662 GETVAL(value, node, "name");
1663 ext->argument = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci8d6b7422017-02-03 14:42:13 +01001664 if (lyp_yin_parse_subnode_ext(module, ext, LYEXT_PAR_EXT, node, LYEXT_SUBSTMT_ARGUMENT, 0, unres)) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001665 goto error;
1666 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09001667
Radek Krejcia1a6b762016-11-14 09:53:38 +09001668 /* yin-element */
Radek Krejcie534c132016-11-23 13:32:31 +01001669 LY_TREE_FOR_SAFE(node->child, next2, child) {
1670 if (child->ns == node->ns && !strcmp(child->name, "yin-element")) {
1671 GETVAL(value, child, "value");
1672 if (ly_strequal(value, "true", 0)) {
1673 ext->flags |= LYS_YINELEM;
1674 }
Radek Krejci1fb02182017-01-24 11:20:55 +01001675
Radek Krejci8d6b7422017-02-03 14:42:13 +01001676 if (lyp_yin_parse_subnode_ext(module, ext, LYEXT_PAR_EXT, child, LYEXT_SUBSTMT_YINELEM, 0, unres)) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001677 goto error;
1678 }
Radek Krejcie534c132016-11-23 13:32:31 +01001679 } else if (child->ns) {
1680 /* unexpected YANG statement */
1681 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->name);
1682 goto error;
1683 } /* else garbage, but save resource needed for unlinking */
Radek Krejcia1a6b762016-11-14 09:53:38 +09001684 }
1685
Radek Krejcie534c132016-11-23 13:32:31 +01001686 lyxml_free(module->ctx, node);
1687 } else {
1688 /* unexpected YANG statement */
1689 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->name);
1690 goto error;
1691 }
1692 }
1693
1694 if (c_ext) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001695 /* some extensions may be already present from the substatements */
1696 reallocated = realloc(ext->ext, (c_ext + ext->ext_size) * sizeof *ext->ext);
1697 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01001698 LOGMEM;
1699 goto error;
1700 }
Radek Krejci1fb02182017-01-24 11:20:55 +01001701 ext->ext = reallocated;
1702
1703 /* init memory */
1704 memset(&ext->ext[ext->ext_size], 0, c_ext * sizeof *ext->ext);
1705
1706 /* process the extension instances of the extension itself */
Radek Krejcie534c132016-11-23 13:32:31 +01001707 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001708 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 +01001709 ext->ext_size++;
1710 if (rc) {
1711 goto error;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001712 }
1713 }
1714 }
1715
Radek Krejci0a498f82017-01-04 16:24:15 +01001716 /* search for plugin */
1717 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 +09001718
1719 return EXIT_SUCCESS;
1720
1721error:
1722 return EXIT_FAILURE;
1723}
1724
Michal Vasko0d343d12015-08-24 14:57:36 +02001725/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001726static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001727fill_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 +02001728{
1729 const char *value;
1730 struct lyxml_elem *child, *next;
Radek Krejcie534c132016-11-23 13:32:31 +01001731 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci5323b492017-01-16 15:40:11 +01001732 void *reallocated;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001733
Radek Krejcib05774c2015-06-18 13:52:59 +02001734 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001735 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001736 goto error;
1737 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001738 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001739 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001740
Radek Krejci07d0fb92017-01-13 14:11:05 +01001741 if (read_yin_common(module, NULL, f, LYEXT_PAR_FEATURE, yin, 0, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001742 goto error;
1743 }
1744
Radek Krejcie534c132016-11-23 13:32:31 +01001745 LY_TREE_FOR(yin->child, child) {
1746 if (strcmp(child->ns->value, LY_NSYIN)) {
1747 /* extension */
1748 c_ext++;
1749 } else if (!strcmp(child->name, "if-feature")) {
1750 c_ftrs++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001751 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001752 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001753 goto error;
1754 }
1755 }
1756
Radek Krejcie534c132016-11-23 13:32:31 +01001757 if (c_ftrs) {
1758 f->iffeature = calloc(c_ftrs, sizeof *f->iffeature);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001759 if (!f->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01001760 LOGMEM;
1761 goto error;
1762 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001763 }
Radek Krejcie534c132016-11-23 13:32:31 +01001764 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01001765 /* some extensions may be already present from the substatements */
1766 reallocated = realloc(f->ext, (c_ext + f->ext_size) * sizeof *f->ext);
1767 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01001768 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001769 goto error;
1770 }
Radek Krejci5323b492017-01-16 15:40:11 +01001771 f->ext = reallocated;
1772
1773 /* init memory */
1774 memset(&f->ext[f->ext_size], 0, c_ext * sizeof *f->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001775 }
1776
Radek Krejcie534c132016-11-23 13:32:31 +01001777 LY_TREE_FOR_SAFE(yin->child, next, child) {
1778 if (strcmp(child->ns->value, LY_NSYIN)) {
1779 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01001780 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 +01001781 f->ext_size++;
1782 if (ret) {
1783 goto error;
1784 }
1785 } else { /* if-feature */
1786 ret = fill_yin_iffeature((struct lys_node *)f, 1, child, &f->iffeature[f->iffeature_size], unres);
1787 f->iffeature_size++;
1788 if (ret) {
1789 goto error;
1790 }
1791 }
1792 }
1793
Radek Krejcic79c6b12016-07-26 15:11:49 +02001794 /* check for circular dependencies */
1795 if (f->iffeature_size) {
1796 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1797 goto error;
1798 }
1799 }
1800
Radek Krejci3cf9e222015-06-18 11:37:50 +02001801 return EXIT_SUCCESS;
1802
1803error:
1804
1805 return EXIT_FAILURE;
1806}
1807
Michal Vasko0d343d12015-08-24 14:57:36 +02001808/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001809static int
Radek Krejcifccd1442017-01-16 10:26:57 +01001810fill_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 +02001811{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001812 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001813
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001814 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001815 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001816 if (!must->expr) {
1817 goto error;
1818 }
Radek Krejci800af702015-06-02 13:46:01 +02001819
Radek Krejciaa9c5202017-02-15 16:10:14 +01001820 return read_restr_substmt(module, must, yin, unres);
Radek Krejci800af702015-06-02 13:46:01 +02001821
Michal Vasko77dc5652016-02-15 12:32:42 +01001822error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001823 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001824}
1825
Radek Krejci581ce772015-11-10 17:22:40 +01001826static int
Radek Krejci7417a082017-02-16 11:07:59 +01001827fill_yin_revision(struct lys_module *module, struct lyxml_elem *yin, struct lys_revision *rev,
1828 struct unres_schema *unres)
1829{
1830 struct lyxml_elem *next, *child;
1831 const char *value;
1832
1833 GETVAL(value, yin, "date");
1834 if (lyp_check_date(value)) {
1835 goto error;
1836 }
1837 memcpy(rev->date, value, LY_REV_SIZE - 1);
1838
1839 LY_TREE_FOR_SAFE(yin->child, next, child) {
1840 if (!child->ns) {
1841 /* garbage */
1842 continue;
1843 } else if (strcmp(child->ns->value, LY_NSYIN)) {
1844 /* possible extension instance */
1845 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1846 child, LYEXT_SUBSTMT_SELF, 0, unres)) {
1847 goto error;
1848 }
1849 } else if (!strcmp(child->name, "description")) {
1850 if (rev->dsc) {
1851 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
1852 goto error;
1853 }
1854 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1855 child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
1856 goto error;
1857 }
1858 rev->dsc = read_yin_subnode(module->ctx, child, "text");
1859 if (!rev->dsc) {
1860 goto error;
1861 }
1862 } else if (!strcmp(child->name, "reference")) {
1863 if (rev->ref) {
1864 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
1865 goto error;
1866 }
1867 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1868 child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
1869 goto error;
1870 }
1871 rev->ref = read_yin_subnode(module->ctx, child, "text");
1872 if (!rev->ref) {
1873 goto error;
1874 }
1875 } else {
1876 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1877 goto error;
1878 }
1879 }
1880
1881 return EXIT_SUCCESS;
1882
1883error:
1884 return EXIT_FAILURE;
1885}
1886
1887static int
Michal Vasko88c29542015-11-27 14:57:53 +01001888fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1889 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001890{
1891 int i, j;
1892 const char *value, *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +02001893 struct unres_list_uniq *unique_info;
Radek Krejci581ce772015-11-10 17:22:40 +01001894
1895 /* get unique value (list of leafs supposed to be unique */
1896 GETVAL(value, yin, "tag");
1897
1898 /* count the number of unique leafs in the value */
1899 vaux = value;
1900 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001901 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001902 while (isspace(*vaux)) {
1903 vaux++;
1904 }
1905 }
1906 unique->expr_size++;
1907 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001908 if (!unique->expr) {
1909 LOGMEM;
1910 goto error;
1911 }
Radek Krejci581ce772015-11-10 17:22:40 +01001912
1913 for (i = 0; i < unique->expr_size; i++) {
1914 vaux = strpbrk(value, " \t\n");
1915 if (!vaux) {
1916 /* the last token, lydict_insert() will count its size on its own */
1917 vaux = value;
1918 }
1919
1920 /* store token into unique structure */
1921 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1922
1923 /* check that the expression does not repeat */
1924 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001925 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001926 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1927 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001928 goto error;
1929 }
1930 }
1931
1932 /* try to resolve leaf */
1933 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001934 unique_info = malloc(sizeof *unique_info);
1935 unique_info->list = parent;
1936 unique_info->expr = unique->expr[i];
1937 unique_info->trg_type = &unique->trg_type;
1938 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1){
Pavol Vican18b10212016-04-11 15:41:52 +02001939 goto error;
1940 }
Radek Krejci581ce772015-11-10 17:22:40 +01001941 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001942 if (resolve_unique(parent, unique->expr[i], &unique->trg_type)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001943 goto error;
1944 }
1945 }
1946
1947 /* move to next token */
1948 value = vaux;
1949 while(isspace(*value)) {
1950 value++;
1951 }
1952 }
1953
1954 return EXIT_SUCCESS;
1955
1956error:
1957 return EXIT_FAILURE;
1958}
1959
Michal Vasko0d343d12015-08-24 14:57:36 +02001960/* logs directly
1961 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001962 * type: 0 - min, 1 - max
1963 */
1964static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001965deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001966{
1967 const char *value;
1968 char *endptr;
1969 unsigned long val;
Pavol Vican09adcc32016-08-25 10:51:36 +02001970 uint32_t *ui32val, *min, *max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001971
Michal Vaskof7e57d52016-03-07 11:31:09 +01001972 /* del min/max is forbidden */
1973 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001974 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001975 goto error;
1976 }
1977
Radek Krejcieb00f512015-07-01 16:44:58 +02001978 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001979 if (target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001980 max = &((struct lys_node_leaflist *)target)->max;
1981 min = &((struct lys_node_leaflist *)target)->min;
Radek Krejci76512572015-08-04 09:47:08 +02001982 } else if (target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001983 max = &((struct lys_node_list *)target)->max;
1984 min = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001985 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001986 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1987 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001988 goto error;
1989 }
1990
1991 GETVAL(value, node, "value");
1992 while (isspace(value[0])) {
1993 value++;
1994 }
1995
Radek Krejci0d7b2472016-02-12 11:11:03 +01001996 if (type && !strcmp(value, "unbounded")) {
1997 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001998 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001999 ui32val = max;
Radek Krejcieb00f512015-07-01 16:44:58 +02002000 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002001 /* convert it to uint32_t */
2002 errno = 0;
2003 endptr = NULL;
2004 val = strtoul(value, &endptr, 10);
2005 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002006 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002007 goto error;
2008 }
2009 if (type) {
2010 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002011 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002012 ui32val = max;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002013 } else {
2014 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01002015 d->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002016 ui32val = min;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002017 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002018 }
2019
2020 if (d->mod == LY_DEVIATE_ADD) {
2021 /* check that there is no current value */
2022 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002023 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
2024 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002025 goto error;
2026 }
Michal Vasko21be1b32016-03-07 12:31:34 +01002027 } else if (d->mod == LY_DEVIATE_RPL) {
2028 /* unfortunately, there is no way to check reliably that there
2029 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02002030 }
2031
Michal Vaskof7e57d52016-03-07 11:31:09 +01002032 /* add (already checked) and replace */
2033 /* set new value specified in deviation */
2034 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02002035
Pavol Vican09adcc32016-08-25 10:51:36 +02002036 /* check min-elements is smaller than max-elements */
2037 if (*max && *min > *max) {
2038 if (type) {
Radek Krejci73f96012016-10-03 13:53:53 +02002039 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "max-elements");
Pavol Vican09adcc32016-08-25 10:51:36 +02002040 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
2041 } else {
Radek Krejci73f96012016-10-03 13:53:53 +02002042 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "min-elements");
Pavol Vican09adcc32016-08-25 10:51:36 +02002043 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
2044 }
2045 goto error;
2046 }
2047
Radek Krejcieb00f512015-07-01 16:44:58 +02002048 return EXIT_SUCCESS;
2049
2050error:
2051
2052 return EXIT_FAILURE;
2053}
2054
Michal Vasko0d343d12015-08-24 14:57:36 +02002055/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002056static int
Michal Vasko88c29542015-11-27 14:57:53 +01002057fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
2058 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02002059{
2060 const char *value, **stritem;
Radek Krejcie534c132016-11-23 13:32:31 +01002061 struct lyxml_elem *next, *next2, *child, *develem;
2062 int c_dev = 0, c_must, c_uniq, c_dflt, c_ext = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002063 int f_min = 0, f_max = 0; /* flags */
Radek Krejci6bd2c022017-02-01 15:04:49 +01002064 int i, j, k, rc;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002065 unsigned int u;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002066 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02002067 struct lys_deviate *d = NULL;
Radek Krejcie00d2312016-08-12 15:27:49 +02002068 struct lys_node *node = NULL, *parent, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002069 struct lys_node_choice *choice = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002070 struct lys_node_leaf *leaf = NULL;
2071 struct ly_set *dflt_check = ly_set_new();
Radek Krejcib8048692015-08-05 13:36:34 +02002072 struct lys_node_list *list = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002073 struct lys_node_leaflist *llist = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002074 struct lys_type *t = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002075 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002076 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01002077 struct unres_schema tmp_unres;
Radek Krejci27fe55e2016-09-13 17:13:35 +02002078 struct lys_module *mod;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002079 void *reallocated;
Radek Krejcieb00f512015-07-01 16:44:58 +02002080
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002081 ctx = module->ctx;
2082
Radek Krejcieb00f512015-07-01 16:44:58 +02002083 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002084 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002085 if (!dev->target_name) {
2086 goto error;
2087 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002088
2089 /* resolve target node */
Radek Krejcidf46e222016-11-08 11:57:37 +01002090 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1, (const struct lys_node **)&dev_target);
Michal Vasko60f4b452016-02-12 11:02:55 +01002091 if (rc || !dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002092 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002093 goto error;
2094 }
Radek Krejcic4283442016-04-22 09:19:27 +02002095 if (dev_target->module == lys_main_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002096 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
2097 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002098 goto error;
2099 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002100
2101 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01002102 if (!child->ns ) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002103 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002104 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002105 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01002106 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2107 /* extension */
2108 c_ext++;
2109 continue;
2110 } else if (!strcmp(child->name, "description")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002111 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002112 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002113 goto error;
2114 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002115 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002116 goto error;
2117 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002118 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002119 if (!dev->dsc) {
2120 goto error;
2121 }
2122 } else if (!strcmp(child->name, "reference")) {
2123 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002124 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002125 goto error;
2126 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002127 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002128 goto error;
2129 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002130 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002131 if (!dev->ref) {
2132 goto error;
2133 }
2134 } else if (!strcmp(child->name, "deviate")) {
2135 c_dev++;
2136
Michal Vasko345da0a2015-12-02 10:35:55 +01002137 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02002138 * further processed later
2139 */
2140 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02002141
Radek Krejcieb00f512015-07-01 16:44:58 +02002142 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002143 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002144 goto error;
2145 }
2146
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002147 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02002148 }
2149
2150 if (c_dev) {
2151 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01002152 if (!dev->deviate) {
2153 LOGMEM;
2154 goto error;
2155 }
Pavol Vican09adcc32016-08-25 10:51:36 +02002156 } else {
2157 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
2158 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002159 }
Radek Krejcie534c132016-11-23 13:32:31 +01002160 if (c_ext) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002161 /* some extensions may be already present from the substatements */
2162 reallocated = realloc(dev->ext, (c_ext + dev->ext_size) * sizeof *dev->ext);
2163 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01002164 LOGMEM;
2165 goto error;
2166 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002167 dev->ext = reallocated;
Radek Krejcieb00f512015-07-01 16:44:58 +02002168
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002169 /* init memory */
2170 memset(&dev->ext[dev->ext_size], 0, c_ext * sizeof *dev->ext);
2171 }
Radek Krejcie534c132016-11-23 13:32:31 +01002172
2173 LY_TREE_FOR_SAFE(yin->child, next, develem) {
2174 if (strcmp(develem->ns->value, LY_NSYIN)) {
2175 /* deviation's extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01002176 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 +01002177 dev->ext_size++;
2178 if (rc) {
2179 goto error;
2180 }
2181 continue;
2182 }
2183
2184 /* deviate */
Radek Krejcieb00f512015-07-01 16:44:58 +02002185 /* init */
2186 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002187 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002188 c_must = 0;
2189 c_uniq = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002190 c_dflt = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01002191 c_ext = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002192
2193 /* get deviation type */
2194 GETVAL(value, develem, "value");
2195 if (!strcmp(value, "not-supported")) {
2196 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002197 /* no other deviate statement is expected,
Radek Krejci5b917642015-07-02 09:03:13 +02002198 * not-supported deviation must be the only deviation of the target
2199 */
2200 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002201 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2202 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02002203 goto error;
2204 }
2205
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002206 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02002207 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
2208 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
2209 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002210 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2211 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002212 goto error;
2213 }
2214 }
2215 }
Radek Krejci5b917642015-07-02 09:03:13 +02002216
Michal Vaskoff006c12016-02-17 11:15:19 +01002217 /* unlink and store the original node */
Radek Krejci30bfcd22017-01-27 16:54:48 +01002218 parent = dev_target->parent;
Michal Vaskoff006c12016-02-17 11:15:19 +01002219 lys_node_unlink(dev_target);
Radek Krejci30bfcd22017-01-27 16:54:48 +01002220 if (parent && parent->nodetype == LYS_AUGMENT) {
2221 /* hack for augment, because when the original will be sometime reconnected back, we actually need
2222 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
2223 * path), so we need to remember the augment as an addition */
2224 dev_target->parent = parent;
2225 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002226 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02002227
Radek Krejcieb00f512015-07-01 16:44:58 +02002228 } else if (!strcmp(value, "add")) {
2229 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
2230 } else if (!strcmp(value, "replace")) {
2231 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
2232 } else if (!strcmp(value, "delete")) {
2233 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
2234 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002235 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002236 goto error;
2237 }
2238 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01002239 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002240
Michal Vaskoff006c12016-02-17 11:15:19 +01002241 /* store a shallow copy of the original node */
2242 if (!dev->orig_node) {
2243 memset(&tmp_unres, 0, sizeof tmp_unres);
Radek Krejci6ff885d2017-01-03 14:06:22 +01002244 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, &tmp_unres, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01002245 /* just to be safe */
2246 if (tmp_unres.count) {
2247 LOGINT;
2248 goto error;
2249 }
2250 }
2251
Radek Krejcieb00f512015-07-01 16:44:58 +02002252 /* process deviation properties */
Radek Krejcie534c132016-11-23 13:32:31 +01002253 LY_TREE_FOR_SAFE(develem->child, next2, child) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002254 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002255 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002256 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002257 continue;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002258 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2259 /* extensions */
2260 c_ext++;
2261 } else if (d->mod == LY_DEVIATE_NO) {
2262 /* no YIN substatement expected in this case */
2263 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2264 goto error;
2265 } else if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002266 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002267 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002268 goto error;
2269 }
2270
2271 /* for we deviate from RFC 6020 and allow config property even it is/is not
2272 * specified in the target explicitly since config property inherits. So we expect
2273 * that config is specified in every node. But for delete, we check that the value
2274 * is the same as here in deviation
2275 */
2276 GETVAL(value, child, "value");
2277 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002278 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02002279 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002280 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02002281 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002282 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002283 goto error;
2284 }
2285
2286 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002287 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002288 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002289 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002290 } else { /* add and replace are the same in this case */
2291 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01002292 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002293
2294 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01002295 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002296 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002297
Radek Krejci8d6b7422017-02-03 14:42:13 +01002298 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002299 goto error;
2300 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002301 } else if (!strcmp(child->name, "default")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002302 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_DEFAULT, c_dflt, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002303 goto error;
2304 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002305 c_dflt++;
2306
2307 /* check target node type */
2308 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
2309 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2310 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
2311 goto error;
2312 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
2313 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2314 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
2315 goto error;
2316 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
2317 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2318 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002319 goto error;
2320 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002321
Radek Krejcid5a5c282016-08-15 15:38:08 +02002322 /* skip lyxml_free() at the end of the loop, this node will be processed later */
2323 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02002324
Radek Krejcieb00f512015-07-01 16:44:58 +02002325 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002326 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002327 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002328 goto error;
2329 }
2330
2331 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002332 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002333 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2334 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002335 goto error;
2336 }
2337
2338 GETVAL(value, child, "value");
2339 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002340 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002341 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002342 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002343 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002344 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002345 goto error;
2346 }
2347
2348 if (d->mod == LY_DEVIATE_ADD) {
2349 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01002350 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002351 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2352 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002353 goto error;
2354 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002355
Radek Krejci841ec082016-04-05 13:05:17 +02002356 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02002357 if (d->flags & LYS_MAND_TRUE) {
2358 if (dev_target->nodetype == LYS_CHOICE) {
2359 if (((struct lys_node_choice *)(dev_target))->dflt) {
2360 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2361 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2362 "Adding the \"mandatory\" statement is forbidden on choice with the \"default\" statement.");
2363 goto error;
2364 }
2365 } else if (dev_target->nodetype == LYS_LEAF) {
2366 if (((struct lys_node_leaf *)(dev_target))->dflt) {
2367 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2368 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2369 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
2370 goto error;
2371 }
2372 }
Radek Krejci841ec082016-04-05 13:05:17 +02002373 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002374
Michal Vasko21be1b32016-03-07 12:31:34 +01002375 dev_target->flags |= d->flags & LYS_MAND_MASK;
2376 } else if (d->mod == LY_DEVIATE_RPL) {
2377 /* check that there was a value before */
2378 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002379 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2380 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002381 goto error;
2382 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002383
Michal Vasko21be1b32016-03-07 12:31:34 +01002384 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01002385 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01002386 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002387 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002388 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002389 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002390 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002391
2392 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2393 for (parent = dev_target->parent;
2394 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2395 parent = parent->parent) {
2396 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2397 /* stop also on presence containers */
2398 break;
2399 }
2400 }
2401 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2402 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2403 if (lyp_check_mandatory_choice(parent)) {
2404 goto error;
2405 }
2406 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002407
Radek Krejci8d6b7422017-02-03 14:42:13 +01002408 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002409 goto error;
2410 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002411 } else if (!strcmp(child->name, "min-elements")) {
2412 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002413 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002414 goto error;
2415 }
2416 f_min = 1;
2417
Michal Vasko60f4b452016-02-12 11:02:55 +01002418 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002419 goto error;
2420 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002421 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002422 goto error;
2423 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002424 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002425 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002426 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002427 goto error;
2428 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01002429 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02002430
Michal Vasko60f4b452016-02-12 11:02:55 +01002431 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002432 goto error;
2433 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002434 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002435 goto error;
2436 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002437 } else if (!strcmp(child->name, "must")) {
2438 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002439 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002440 continue;
2441 } else if (!strcmp(child->name, "type")) {
2442 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002443 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002444 goto error;
2445 }
2446
Michal Vaskof7e57d52016-03-07 11:31:09 +01002447 /* add, del type is forbidden */
2448 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002449 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002450 goto error;
2451 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002452 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002453 goto error;
2454 }
2455
Radek Krejcieb00f512015-07-01 16:44:58 +02002456 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002457 if (dev_target->nodetype == LYS_LEAF) {
2458 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002459 if (((struct lys_node_leaf *)dev_target)->dflt) {
2460 ly_set_add(dflt_check, dev_target, 0);
2461 }
Michal Vasko60f4b452016-02-12 11:02:55 +01002462 } else if (dev_target->nodetype == LYS_LEAFLIST) {
2463 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002464 if (((struct lys_node_leaflist *)dev_target)->dflt) {
2465 ly_set_add(dflt_check, dev_target, 0);
2466 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002467 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002468 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2469 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002470 goto error;
2471 }
2472
Radek Krejcieb00f512015-07-01 16:44:58 +02002473 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002474 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01002475 /* HACK for unres */
2476 t->der = (struct lys_tpdf *)child;
Michal Vasko3767fb22016-07-21 12:10:57 +02002477 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002478 goto error;
2479 }
2480 d->type = t;
2481 } else if (!strcmp(child->name, "unique")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002482 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_UNIQUE, c_uniq, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002483 goto error;
2484 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002485 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002486 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002487 continue;
2488 } else if (!strcmp(child->name, "units")) {
2489 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002490 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002491 goto error;
2492 }
2493
2494 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002495 if (dev_target->nodetype == LYS_LEAFLIST) {
2496 stritem = &((struct lys_node_leaflist *)dev_target)->units;
2497 } else if (dev_target->nodetype == LYS_LEAF) {
2498 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02002499 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002500 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2501 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002502 goto error;
2503 }
2504
2505 /* get units value */
2506 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002507 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02002508
2509 /* apply to target */
2510 if (d->mod == LY_DEVIATE_ADD) {
2511 /* check that there is no current value */
2512 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002513 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2514 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002515 goto error;
2516 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002517
Michal Vasko21be1b32016-03-07 12:31:34 +01002518 *stritem = lydict_insert(ctx, value, 0);
2519 } else if (d->mod == LY_DEVIATE_RPL) {
2520 /* check that there was a value before */
2521 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002522 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2523 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01002524 goto error;
2525 }
2526
2527 lydict_remove(ctx, *stritem);
2528 *stritem = lydict_insert(ctx, value, 0);
2529 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002530 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002531 if (!ly_strequal(*stritem, d->units, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002532 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2533 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002534 goto error;
2535 }
2536 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002537 lydict_remove(ctx, *stritem);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002538 (*stritem) = NULL;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002539
2540 /* remove its extensions */
2541 j = -1;
2542 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_UNITS)) != -1) {
2543 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2544 --j;
2545 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002546 }
2547
Radek Krejci8d6b7422017-02-03 14:42:13 +01002548 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002549 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002550 }
2551 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002552 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002553 goto error;
2554 }
2555
Michal Vasko88c29542015-11-27 14:57:53 +01002556 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002557 }
2558
2559 if (c_must) {
2560 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002561 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002562 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002563 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2564 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002565 break;
Radek Krejci76512572015-08-04 09:47:08 +02002566 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002567 trg_must = &((struct lys_node_container *)dev_target)->must;
2568 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002569 break;
Radek Krejci76512572015-08-04 09:47:08 +02002570 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002571 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2572 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002573 break;
Radek Krejci76512572015-08-04 09:47:08 +02002574 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002575 trg_must = &((struct lys_node_list *)dev_target)->must;
2576 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002577 break;
Radek Krejci76512572015-08-04 09:47:08 +02002578 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002579 case LYS_ANYDATA:
2580 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2581 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002582 break;
2583 default:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002584 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2585 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002586 goto error;
2587 }
2588
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002589 dev_target->flags &= ~LYS_XPATH_DEP;
Michal Vasko508a50d2016-09-07 14:50:33 +02002590
Radek Krejcieb00f512015-07-01 16:44:58 +02002591 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002592 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002593 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002594 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002595 } else if (d->mod == LY_DEVIATE_ADD) {
2596 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002597 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002598 if (!d->must) {
2599 LOGMEM;
2600 goto error;
2601 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002602 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02002603 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002604 d->must_size = c_must;
2605 } else { /* LY_DEVIATE_DEL */
2606 d->must = calloc(c_must, sizeof *d->must);
2607 }
Michal Vasko253035f2015-12-17 16:58:13 +01002608 if (!d->must) {
2609 LOGMEM;
2610 goto error;
2611 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002612 }
2613 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002614 /* replace unique is forbidden */
2615 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002616 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002617 goto error;
2618 }
2619
Radek Krejcieb00f512015-07-01 16:44:58 +02002620 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002621 if (dev_target->nodetype != LYS_LIST) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002622 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2623 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002624 goto error;
2625 }
2626
Michal Vasko60f4b452016-02-12 11:02:55 +01002627 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002628 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002629 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002630 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02002631 list->unique = d->unique;
2632 d->unique = &list->unique[list->unique_size];
2633 d->unique_size = c_uniq;
2634 } else { /* LY_DEVIATE_DEL */
2635 d->unique = calloc(c_uniq, sizeof *d->unique);
2636 }
Michal Vasko253035f2015-12-17 16:58:13 +01002637 if (!d->unique) {
2638 LOGMEM;
2639 goto error;
2640 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002641 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002642 if (c_dflt) {
2643 if (d->mod == LY_DEVIATE_ADD) {
2644 /* check that there is no current value */
2645 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
2646 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
2647 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2648 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
2649 goto error;
2650 }
2651
2652 /* check collision with mandatory/min-elements */
2653 if ((dev_target->flags & LYS_MAND_TRUE) ||
2654 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
2655 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2656 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2657 "Adding the \"default\" statement is forbidden on %s statement.",
2658 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2659 goto error;
2660 }
2661 } else if (d->mod == LY_DEVIATE_RPL) {
2662 /* check that there was a value before */
2663 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2664 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
2665 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2666 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
2667 goto error;
2668 }
2669 }
2670
2671 if (dev_target->nodetype == LYS_LEAFLIST) {
2672 /* reallocate default list in the target */
2673 llist = (struct lys_node_leaflist *)dev_target;
2674 if (d->mod == LY_DEVIATE_ADD) {
2675 /* reallocate (enlarge) the unique array of the target */
2676 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
2677 } else if (d->mod == LY_DEVIATE_RPL) {
2678 /* reallocate (replace) the unique array of the target */
2679 for (i = 0; i < llist->dflt_size; i++) {
2680 lydict_remove(llist->module->ctx, llist->dflt[i]);
2681 }
2682 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2683 llist->dflt_size = 0;
2684 }
2685 }
2686 d->dflt = calloc(c_dflt, sizeof *d->dflt);
2687 if (!d->dflt) {
2688 LOGMEM;
2689 goto error;
2690 }
2691 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002692 if (c_ext) {
2693 /* some extensions may be already present from the substatements */
2694 reallocated = realloc(d->ext, (c_ext + d->ext_size) * sizeof *d->ext);
2695 if (!reallocated) {
2696 LOGMEM;
2697 goto error;
2698 }
2699 d->ext = reallocated;
2700
2701 /* init memory */
2702 memset(&d->ext[d->ext_size], 0, c_ext * sizeof *d->ext);
2703 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002704
2705 /* process deviation properties with 0..n cardinality */
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002706 LY_TREE_FOR_SAFE(develem->child, next2, child) {
2707 if (strcmp(child->ns->value, LY_NSYIN)) {
2708 /* extension */
2709 if (lyp_yin_fill_ext(d, LYEXT_PAR_DEVIATE, 0, 0, module, child, &d->ext, d->ext_size, unres)) {
2710 goto error;
2711 }
2712 d->ext_size++;
2713 } else if (!strcmp(child->name, "must")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002714 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcifccd1442017-01-16 10:26:57 +01002715 if (fill_yin_must(module, child, &d->must[d->must_size], unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002716 goto error;
2717 }
2718
2719 /* find must to delete, we are ok with just matching conditions */
2720 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002721 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002722 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002723 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02002724 /* ... and maintain the array */
2725 (*trg_must_size)--;
2726 if (i != *trg_must_size) {
2727 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2728 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2729 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2730 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2731 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2732 }
2733 if (!(*trg_must_size)) {
2734 free(*trg_must);
2735 *trg_must = NULL;
2736 } else {
2737 (*trg_must)[*trg_must_size].expr = NULL;
2738 (*trg_must)[*trg_must_size].dsc = NULL;
2739 (*trg_must)[*trg_must_size].ref = NULL;
2740 (*trg_must)[*trg_must_size].eapptag = NULL;
2741 (*trg_must)[*trg_must_size].emsg = NULL;
2742 }
2743
2744 i = -1; /* set match flag */
2745 break;
2746 }
2747 }
2748 d->must_size++;
2749 if (i != -1) {
2750 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002751 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002752 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01002753 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002754 goto error;
2755 }
2756 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002757 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
Radek Krejcifccd1442017-01-16 10:26:57 +01002758 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]), unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002759 goto error;
2760 }
2761 (*trg_must_size)++;
2762 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002763
2764 /* check XPath dependencies again */
Michal Vaskoe8734262016-09-29 14:12:06 +02002765 if (*trg_must_size && unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02002766 goto error;
2767 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002768 } else if (!strcmp(child->name, "unique")) {
2769 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002770 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002771 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002772 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002773 goto error;
2774 }
2775
2776 /* find unique structures to delete */
2777 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002778 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002779 continue;
2780 }
2781
Radek Krejci581ce772015-11-10 17:22:40 +01002782 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002783 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002784 break;
2785 }
2786 }
2787
Radek Krejci581ce772015-11-10 17:22:40 +01002788 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002789 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002790 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002791 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002792 }
2793 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002794 /* ... and maintain the array */
2795 list->unique_size--;
2796 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002797 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2798 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002799 }
2800
2801 if (!list->unique_size) {
2802 free(list->unique);
2803 list->unique = NULL;
2804 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002805 list->unique[list->unique_size].expr_size = 0;
2806 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002807 }
2808
Radek Krejci6bd2c022017-02-01 15:04:49 +01002809 k = i; /* remember index for removing extensions */
Radek Krejcieb00f512015-07-01 16:44:58 +02002810 i = -1; /* set match flag */
2811 break;
2812 }
2813 }
2814
2815 d->unique_size++;
2816 if (i != -1) {
2817 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002818 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2819 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002820 goto error;
2821 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01002822
2823 /* remove extensions of this unique instance from the target node */
2824 j = -1;
2825 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_UNIQUE)) != -1) {
Radek Krejcifebdad72017-02-06 11:35:51 +01002826 if (dev_target->ext[j]->insubstmt_index == k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002827 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2828 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01002829 } else if (dev_target->ext[j]->insubstmt_index > k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002830 /* decrease the substatement index of the extension because of the changed array of uniques */
Radek Krejcifebdad72017-02-06 11:35:51 +01002831 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002832 }
2833 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002834 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002835 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002836 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002837 list->unique_size++;
2838 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002839 goto error;
2840 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002841 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002842 } else if (!strcmp(child->name, "default")) {
2843 GETVAL(value, child, "value");
2844 u = strlen(value);
2845 d->dflt[d->dflt_size++] = lydict_insert(module->ctx, value, u);
2846
2847 if (dev_target->nodetype == LYS_CHOICE) {
2848 choice = (struct lys_node_choice *)dev_target;
2849 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2850 if (rc || !node) {
2851 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2852 goto error;
2853 }
2854 if (d->mod == LY_DEVIATE_DEL) {
2855 if (!choice->dflt || (choice->dflt != node)) {
2856 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2857 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2858 goto error;
2859 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01002860 choice->dflt = NULL;
2861 /* remove extensions of this default instance from the target node */
2862 j = -1;
2863 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
2864 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2865 --j;
2866 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002867 } else { /* add or replace */
2868 choice->dflt = node;
2869 if (!choice->dflt) {
2870 /* default branch not found */
2871 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2872 goto error;
2873 }
2874 }
2875 } else if (dev_target->nodetype == LYS_LEAF) {
2876 leaf = (struct lys_node_leaf *)dev_target;
2877 if (d->mod == LY_DEVIATE_DEL) {
2878 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
2879 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2880 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2881 goto error;
2882 }
2883 /* remove value */
2884 lydict_remove(ctx, leaf->dflt);
2885 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01002886 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002887
2888 /* remove extensions of this default instance from the target node */
2889 j = -1;
2890 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
2891 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2892 --j;
2893 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002894 } else { /* add (already checked) and replace */
2895 /* remove value */
2896 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01002897 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002898
2899 /* set new value */
2900 leaf->dflt = lydict_insert(ctx, value, u);
2901
Radek Krejcibd117f02016-11-04 16:28:08 +01002902 /* remember to check it later (it may not fit now, because the type can be deviated too) */
Radek Krejcid5a5c282016-08-15 15:38:08 +02002903 ly_set_add(dflt_check, dev_target, 0);
2904 }
2905 } else { /* LYS_LEAFLIST */
2906 llist = (struct lys_node_leaflist *)dev_target;
2907 if (d->mod == LY_DEVIATE_DEL) {
2908 /* find and remove the value in target list */
2909 for (i = 0; i < llist->dflt_size; i++) {
2910 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
2911 /* match, remove the value */
2912 lydict_remove(llist->module->ctx, llist->dflt[i]);
2913 llist->dflt[i] = NULL;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002914
2915 /* remove extensions of this default instance from the target node */
2916 j = -1;
2917 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
Radek Krejcifebdad72017-02-06 11:35:51 +01002918 if (dev_target->ext[j]->insubstmt_index == i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002919 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2920 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01002921 } else if (dev_target->ext[j]->insubstmt_index > i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002922 /* decrease the substatement index of the extension because of the changed array of defaults */
Radek Krejcifebdad72017-02-06 11:35:51 +01002923 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002924 }
2925 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002926 break;
2927 }
2928 }
2929 if (i == llist->dflt_size) {
2930 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2931 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
2932 goto error;
2933 }
2934 } else {
2935 /* add or replace, anyway we place items into the deviate's list
2936 which propagates to the target */
2937 /* we just want to check that the value isn't already in the list */
2938 for (i = 0; i < llist->dflt_size; i++) {
2939 if (ly_strequal(llist->dflt[i], value, 1)) {
2940 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2941 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2942 goto error;
2943 }
2944 }
2945 /* store it in target node */
2946 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, u);
2947
2948 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2949 ly_set_add(dflt_check, dev_target, 0);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002950 llist->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002951 }
2952 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002953 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002954 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002955
2956 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
2957 /* consolidate the final list in the target after removing items from it */
2958 llist = (struct lys_node_leaflist *)dev_target;
2959 for (i = j = 0; j < llist->dflt_size; j++) {
2960 llist->dflt[i] = llist->dflt[j];
2961 if (llist->dflt[i]) {
2962 i++;
2963 }
2964 }
2965 llist->dflt_size = i + 1;
2966 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002967 }
2968
Michal Vasko43a1feb2016-03-07 12:03:02 +01002969 /* now check whether default value, if any, matches the type */
Pavol Vican85991ec2016-08-16 14:58:12 +02002970 for (u = 0; u < dflt_check->number; ++u) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002971 value = NULL;
2972 rc = EXIT_SUCCESS;
2973 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2974 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
Radek Krejci51673202016-11-01 17:00:32 +01002975 value = leaf->dflt;
2976 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002977 } else { /* LYS_LEAFLIST */
2978 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2979 for (j = 0; j < llist->dflt_size; j++) {
Radek Krejci51673202016-11-01 17:00:32 +01002980 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2981 (struct lys_node *)(&llist->dflt[j]));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002982 if (rc == -1) {
Radek Krejci51673202016-11-01 17:00:32 +01002983 value = llist->dflt[j];
Radek Krejcid5a5c282016-08-15 15:38:08 +02002984 break;
2985 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002986 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002987
2988 }
2989 if (rc == -1) {
2990 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2991 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2992 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2993 dev->target_name);
2994 goto error;
Michal Vasko43a1feb2016-03-07 12:03:02 +01002995 }
2996 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002997
Radek Krejci27fe55e2016-09-13 17:13:35 +02002998 /* mark all the affected modules as deviated and implemented */
2999 for(parent = dev_target; parent; parent = lys_parent(parent)) {
3000 mod = lys_node_module(parent);
3001 if (module != mod) {
3002 mod->deviated = 1;
Radek Krejci2bb5be72017-02-27 13:07:25 +01003003 if (lys_set_implemented(mod)) {
3004 LOGERR(ly_errno, "Setting the deviated module \"%s\" implemented failed.", mod->name);
3005 goto error;
3006 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02003007 }
3008 }
3009
Radek Krejcid5a5c282016-08-15 15:38:08 +02003010 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02003011 return EXIT_SUCCESS;
3012
3013error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02003014 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02003015 return EXIT_FAILURE;
3016}
3017
Michal Vasko0d343d12015-08-24 14:57:36 +02003018/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02003019static int
Radek Krejcib8048692015-08-05 13:36:34 +02003020fill_yin_augment(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_node_augment *aug,
Radek Krejci7212e0a2017-03-08 15:58:22 +01003021 int options, struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02003022{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003023 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003024 struct lyxml_elem *sub, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003025 struct lys_node *node;
Radek Krejcie534c132016-11-23 13:32:31 +01003026 int ret, c_ftrs = 0, c_ext = 0;
Radek Krejci30701b42017-01-23 16:41:38 +01003027 void *reallocated;
Radek Krejci106efc02015-06-10 14:36:27 +02003028
Michal Vasko591e0b22015-08-13 13:53:43 +02003029 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003030 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003031 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02003032 if (!aug->target_name) {
3033 goto error;
3034 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003035 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02003036
Radek Krejci07d0fb92017-01-13 14:11:05 +01003037 if (read_yin_common(module, NULL, aug, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003038 goto error;
3039 }
3040
Radek Krejcie534c132016-11-23 13:32:31 +01003041 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3042 if (strcmp(sub->ns->value, LY_NSYIN)) {
3043 /* extension */
3044 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003045 continue;
Radek Krejci30701b42017-01-23 16:41:38 +01003046 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejcie534c132016-11-23 13:32:31 +01003047 c_ftrs++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003048 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003049 } else if (!strcmp(sub->name, "when")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003050 if (aug->when) {
Radek Krejcie534c132016-11-23 13:32:31 +01003051 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003052 goto error;
3053 }
3054
Radek Krejci5323b492017-01-16 15:40:11 +01003055 aug->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003056 if (!aug->when) {
Radek Krejcie534c132016-11-23 13:32:31 +01003057 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003058 goto error;
3059 }
Radek Krejcie534c132016-11-23 13:32:31 +01003060 lyxml_free(module->ctx, sub);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003061 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003062
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003063 /* check allowed data sub-statements */
Radek Krejcie534c132016-11-23 13:32:31 +01003064 } else if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003065 node = read_yin_container(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003066 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003067 node = read_yin_leaflist(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003068 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003069 node = read_yin_leaf(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003070 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003071 node = read_yin_list(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003072 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003073 node = read_yin_uses(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003074 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003075 node = read_yin_choice(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003076 } else if (!strcmp(sub->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003077 node = read_yin_case(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003078 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003079 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYXML, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003080 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003081 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYDATA, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003082 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003083 node = read_yin_rpc_action(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003084 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003085 node = read_yin_notif(module, (struct lys_node *)aug, sub, options, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003086 } else {
Radek Krejcie534c132016-11-23 13:32:31 +01003087 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003088 goto error;
3089 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003090
Radek Krejci1d82ef62015-08-07 14:44:40 +02003091 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003092 goto error;
3093 }
3094
Radek Krejci1d82ef62015-08-07 14:44:40 +02003095 node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01003096 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003097 }
3098
Radek Krejcie534c132016-11-23 13:32:31 +01003099 if (c_ftrs) {
3100 aug->iffeature = calloc(c_ftrs, sizeof *aug->iffeature);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003101 if (!aug->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003102 LOGMEM;
3103 goto error;
3104 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003105 }
Radek Krejcie534c132016-11-23 13:32:31 +01003106 if (c_ext) {
Radek Krejci30701b42017-01-23 16:41:38 +01003107 /* some extensions may be already present from the substatements */
3108 reallocated = realloc(aug->ext, (c_ext + aug->ext_size) * sizeof *aug->ext);
3109 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003110 LOGMEM;
3111 goto error;
3112 }
Radek Krejci30701b42017-01-23 16:41:38 +01003113 aug->ext = reallocated;
3114
3115 /* init memory */
3116 memset(&aug->ext[aug->ext_size], 0, c_ext * sizeof *aug->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003117 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003118
Radek Krejcie534c132016-11-23 13:32:31 +01003119 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3120 if (strcmp(sub->ns->value, LY_NSYIN)) {
3121 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003122 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 +01003123 aug->ext_size++;
3124 if (ret) {
3125 goto error;
3126 }
3127 } else if (!strcmp(sub->name, "if-feature")) {
3128 ret = fill_yin_iffeature((struct lys_node *)aug, 0, sub, &aug->iffeature[aug->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003129 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003130 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003131 goto error;
3132 }
Radek Krejcie534c132016-11-23 13:32:31 +01003133 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003134 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003135 }
3136
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003137 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02003138 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02003139 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02003140 * when the uses does and cannot be resolved now for sure
3141 * (the grouping was not yet copied into uses).
3142 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02003143 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003144 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02003145 goto error;
3146 }
Michal Vasko49291b32015-08-06 09:49:41 +02003147 }
Radek Krejci106efc02015-06-10 14:36:27 +02003148
Michal Vasko508a50d2016-09-07 14:50:33 +02003149 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01003150 if (aug->when) {
3151 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003152 if (lyxp_node_check_syntax((struct lys_node *)aug)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003153 goto error;
3154 }
3155 } else {
3156 if (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1) {
3157 goto error;
3158 }
3159 }
Michal Vasko508a50d2016-09-07 14:50:33 +02003160 }
3161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003162 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02003163
3164error:
3165
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003166 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02003167}
3168
Michal Vasko0d343d12015-08-24 14:57:36 +02003169/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003170static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02003171fill_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 +02003172{
Radek Krejci363bd4a2016-07-29 14:30:20 +02003173 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003174 struct lyxml_elem *sub, *next;
3175 const char *value;
3176 char *endptr;
3177 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01003178 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003179 int r;
3180 unsigned long int val;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003181 void *reallocated;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003182
Radek Krejci363bd4a2016-07-29 14:30:20 +02003183 assert(uses);
3184 module = uses->module; /* shorthand */
3185
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003186 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003187 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02003188 if (!rfn->target_name) {
3189 goto error;
3190 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003191
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003192 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003193 if (!sub->ns) {
3194 /* garbage */
3195 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01003196 /* extension */
3197 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003198 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02003199
Radek Krejci411b1bf2017-01-23 16:40:05 +01003200 } else if (!strcmp(sub->name, "description")) {
3201 if (rfn->dsc) {
3202 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3203 goto error;
3204 }
3205
Radek Krejci8d6b7422017-02-03 14:42:13 +01003206 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003207 goto error;
3208 }
3209
3210 rfn->dsc = read_yin_subnode(module->ctx, sub, "text");
3211 if (!rfn->dsc) {
3212 goto error;
3213 }
3214 } else if (!strcmp(sub->name, "reference")) {
3215 if (rfn->ref) {
3216 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3217 goto error;
3218 }
3219
Radek Krejci8d6b7422017-02-03 14:42:13 +01003220 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003221 goto error;
3222 }
3223
3224 rfn->ref = read_yin_subnode(module->ctx, sub, "text");
3225 if (!rfn->ref) {
3226 goto error;
3227 }
3228 } else if (!strcmp(sub->name, "config")) {
3229 if (rfn->flags & LYS_CONFIG_MASK) {
3230 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3231 goto error;
3232 }
3233 GETVAL(value, sub, "value");
3234 if (!strcmp(value, "false")) {
3235 rfn->flags |= LYS_CONFIG_R;
3236 } else if (!strcmp(value, "true")) {
3237 rfn->flags |= LYS_CONFIG_W;
3238 } else {
3239 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3240 goto error;
3241 }
3242 rfn->flags |= LYS_CONFIG_SET;
3243
Radek Krejci8d6b7422017-02-03 14:42:13 +01003244 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003245 goto error;
3246 }
Radek Krejcie534c132016-11-23 13:32:31 +01003247 } else if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02003248 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02003249
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003250 /* check possibility of statements combination */
3251 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02003252 if (c_dflt) {
3253 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003254 if (module->version < 2) {
3255 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3256 goto error;
3257 }
Radek Krejci200bf712016-08-16 17:11:04 +02003258 rfn->target_type &= LYS_LEAFLIST;
3259 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003260 if (module->version < 2) {
3261 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
3262 } else {
3263 /* YANG 1.1 */
3264 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
3265 }
Radek Krejci200bf712016-08-16 17:11:04 +02003266 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003267 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003268 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3269 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003270 goto error;
3271 }
3272 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003273 if (module->version < 2) {
3274 rfn->target_type = LYS_LEAF | LYS_CHOICE;
3275 } else {
3276 /* YANG 1.1 */
3277 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
3278 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003279 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003280
Radek Krejci8d6b7422017-02-03 14:42:13 +01003281 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DEFAULT, c_dflt, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003282 goto error;
3283 }
Radek Krejci200bf712016-08-16 17:11:04 +02003284 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003285 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003286 } else if (!strcmp(sub->name, "mandatory")) {
3287 /* leaf, choice or anyxml */
3288 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003289 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003290 goto error;
3291 }
3292 /* just checking the flags in leaf is not sufficient, we would allow
3293 * multiple mandatory statements with the "false" value
3294 */
3295 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003296
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003297 /* check possibility of statements combination */
3298 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003299 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003300 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003301 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3302 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003303 goto error;
3304 }
3305 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003306 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003307 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003308
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003309 GETVAL(value, sub, "value");
3310 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003311 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003312 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003313 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003314 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003315 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003316 goto error;
3317 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003318 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003319 goto error;
3320 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003321 } else if (!strcmp(sub->name, "min-elements")) {
3322 /* list or leaf-list */
3323 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003324 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003325 goto error;
3326 }
3327 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003328
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003329 /* check possibility of statements combination */
3330 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003331 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003332 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003333 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3334 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003335 goto error;
3336 }
3337 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003338 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003339 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003340
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003341 GETVAL(value, sub, "value");
3342 while (isspace(value[0])) {
3343 value++;
3344 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003345
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003346 /* convert it to uint32_t */
3347 errno = 0;
3348 endptr = NULL;
3349 val = strtoul(value, &endptr, 10);
3350 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003351 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003352 goto error;
3353 }
3354 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003355 rfn->flags |= LYS_RFN_MINSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003356
Radek Krejci8d6b7422017-02-03 14:42:13 +01003357 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003358 goto error;
3359 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003360 } else if (!strcmp(sub->name, "max-elements")) {
3361 /* list or leaf-list */
3362 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003363 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003364 goto error;
3365 }
3366 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003367
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003368 /* check possibility of statements combination */
3369 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003370 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003371 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003372 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3373 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003374 goto error;
3375 }
3376 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003377 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003378 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003380 GETVAL(value, sub, "value");
3381 while (isspace(value[0])) {
3382 value++;
3383 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003384
Radek Krejci0d7b2472016-02-12 11:11:03 +01003385 if (!strcmp(value, "unbounded")) {
3386 rfn->mod.list.max = 0;
3387 } else {
3388 /* convert it to uint32_t */
3389 errno = 0;
3390 endptr = NULL;
3391 val = strtoul(value, &endptr, 10);
3392 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003393 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003394 goto error;
3395 }
3396 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003397 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003398 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003399
Radek Krejci8d6b7422017-02-03 14:42:13 +01003400 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003401 goto error;
3402 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003403 } else if (!strcmp(sub->name, "presence")) {
3404 /* container */
3405 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003406 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003407 goto error;
3408 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003409
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003410 /* check possibility of statements combination */
3411 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003412 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003413 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003414 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3415 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003416 goto error;
3417 }
3418 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003419 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003420 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003421
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003422 GETVAL(value, sub, "value");
3423 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcifdc0d702017-01-23 15:58:38 +01003424
Radek Krejci8d6b7422017-02-03 14:42:13 +01003425 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003426 goto error;
3427 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003428 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02003429 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003430 /* check possibility of statements combination */
3431 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003432 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003433 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003434 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3435 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003436 goto error;
3437 }
3438 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003439 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003440 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003441
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003442 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003443 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003444
Radek Krejci363bd4a2016-07-29 14:30:20 +02003445 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
3446 /* leaf, leaf-list, list, container or anyxml */
3447 /* check possibility of statements combination */
3448 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003449 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003450 if (!rfn->target_type) {
3451 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3452 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
3453 goto error;
3454 }
3455 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003456 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003457 }
3458
3459 c_ftrs++;
3460 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003461 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003462 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003463 goto error;
3464 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003465
Michal Vasko345da0a2015-12-02 10:35:55 +01003466 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003467 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003468
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003469 /* process nodes with cardinality of 0..n */
3470 if (c_must) {
3471 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003472 if (!rfn->must) {
3473 LOGMEM;
3474 goto error;
3475 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003476 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02003477 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02003478 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003479 if (!rfn->iffeature) {
3480 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02003481 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003482 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003483 }
Radek Krejci200bf712016-08-16 17:11:04 +02003484 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003485 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Radek Krejci200bf712016-08-16 17:11:04 +02003486 if (!rfn->dflt) {
3487 LOGMEM;
3488 goto error;
3489 }
3490 }
Radek Krejcie534c132016-11-23 13:32:31 +01003491 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003492 /* some extensions may be already present from the substatements */
3493 reallocated = realloc(rfn->ext, (c_ext + rfn->ext_size) * sizeof *rfn->ext);
3494 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003495 LOGMEM;
3496 goto error;
3497 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01003498 rfn->ext = reallocated;
3499
3500 /* init memory */
3501 memset(&rfn->ext[rfn->ext_size], 0, c_ext * sizeof *rfn->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003502 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003503
Radek Krejcie534c132016-11-23 13:32:31 +01003504 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3505 if (strcmp(sub->ns->value, LY_NSYIN)) {
3506 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003507 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 +01003508 rfn->ext_size++;
3509 if (r) {
3510 goto error;
3511 }
3512 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003513 r = fill_yin_iffeature(uses, 0, sub, &rfn->iffeature[rfn->iffeature_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003514 rfn->iffeature_size++;
3515 if (r) {
3516 goto error;
3517 }
Radek Krejci200bf712016-08-16 17:11:04 +02003518 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01003519 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003520 rfn->must_size++;
3521 if (r) {
3522 goto error;
3523 }
Radek Krejci200bf712016-08-16 17:11:04 +02003524 } else { /* default */
3525 GETVAL(value, sub, "value");
3526
3527 /* check for duplicity */
3528 for (r = 0; r < rfn->dflt_size; r++) {
3529 if (ly_strequal(rfn->dflt[r], value, 1)) {
3530 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3531 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
3532 goto error;
3533 }
3534 }
3535 rfn->dflt[rfn->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02003536 }
3537 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003538
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003539 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003540
3541error:
3542
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003543 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003544}
3545
Michal Vasko0d343d12015-08-24 14:57:36 +02003546/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003547static int
Radek Krejcie534c132016-11-23 13:32:31 +01003548fill_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 +02003549{
Radek Krejcie534c132016-11-23 13:32:31 +01003550 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003551 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003552 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003553 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003554
Radek Krejcie534c132016-11-23 13:32:31 +01003555 /* init */
3556 memset(&exts, 0, sizeof exts);
3557
3558 LY_TREE_FOR_SAFE(yin->child, next, child) {
3559 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003560 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003561 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003562 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3563 /* extension */
3564 c_ext++;
3565 lyxml_unlink_elem(module->ctx, child, 2);
3566 lyxml_add_child(module->ctx, &exts, child);
3567 } else if (!strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003568 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01003569 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003570 goto error;
3571 }
3572 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01003573
Radek Krejci8d6b7422017-02-03 14:42:13 +01003574 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003575 goto error;
3576 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003577 } else if (!strcmp(child->name, "revision-date")) {
3578 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02003579 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3580 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003581 }
3582 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003583 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003584 goto error;
3585 }
3586 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003587
Radek Krejci8d6b7422017-02-03 14:42:13 +01003588 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003589 goto error;
3590 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003591 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003592 if (imp->dsc) {
3593 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3594 goto error;
3595 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003596 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003597 goto error;
3598 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003599 imp->dsc = read_yin_subnode(module->ctx, child, "text");
3600 if (!imp->dsc) {
3601 goto error;
3602 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003603 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003604 if (imp->ref) {
3605 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3606 goto error;
3607 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003608 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003609 goto error;
3610 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003611 imp->ref = read_yin_subnode(module->ctx, child, "text");
3612 if (!imp->ref) {
3613 goto error;
3614 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003615 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003616 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003617 goto error;
3618 }
3619 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003620
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003621 /* check mandatory information */
3622 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003623 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003624 goto error;
3625 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003626
Radek Krejcie534c132016-11-23 13:32:31 +01003627 /* process extensions */
3628 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003629 /* some extensions may be already present from the substatements */
3630 reallocated = realloc(imp->ext, (c_ext + imp->ext_size) * sizeof *imp->ext);
3631 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003632 LOGMEM;
3633 goto error;
3634 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003635 imp->ext = reallocated;
3636
3637 /* init memory */
3638 memset(&imp->ext[imp->ext_size], 0, c_ext * sizeof *imp->ext);
3639
Radek Krejcie534c132016-11-23 13:32:31 +01003640 LY_TREE_FOR_SAFE(exts.child, next, child) {
3641 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003642 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 +01003643 imp->ext_size++;
3644 if (r) {
3645 goto error;
3646 }
3647 }
3648 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003649
Radek Krejcie534c132016-11-23 13:32:31 +01003650 GETVAL(value, yin, "module");
Pavol Vicane994fda2016-03-22 10:47:58 +01003651 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02003652
3653error:
3654
Radek Krejcie534c132016-11-23 13:32:31 +01003655 while (exts.child) {
3656 lyxml_free(module->ctx, exts.child);
3657 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003658 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02003659}
3660
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003661/* logs directly
3662 * returns:
3663 * 0 - inc successfully filled
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003664 * -1 - error
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003665 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003666static int
Michal Vasko5ff78822016-02-12 09:33:31 +01003667fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
3668 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02003669{
Radek Krejcie534c132016-11-23 13:32:31 +01003670 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003671 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003672 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003673 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003674
Radek Krejcie534c132016-11-23 13:32:31 +01003675 /* init */
3676 memset(&exts, 0, sizeof exts);
3677
3678 LY_TREE_FOR_SAFE(yin->child, next, child) {
3679 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003680 /* garbage */
3681 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003682 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3683 /* extension */
3684 c_ext++;
3685 lyxml_unlink_elem(module->ctx, child, 2);
3686 lyxml_add_child(module->ctx, &exts, child);
3687 } else if (!strcmp(child->name, "revision-date")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003688 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003689 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003690 goto error;
3691 }
3692 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003693 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003694 goto error;
3695 }
3696 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003697
Radek Krejci8d6b7422017-02-03 14:42:13 +01003698 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003699 goto error;
3700 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003701 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003702 if (inc->dsc) {
3703 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3704 goto error;
3705 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003706 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003707 goto error;
3708 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003709 inc->dsc = read_yin_subnode(module->ctx, child, "text");
3710 if (!inc->dsc) {
3711 goto error;
3712 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003713 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003714 if (inc->ref) {
3715 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3716 goto error;
3717 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003718 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003719 goto error;
3720 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003721 inc->ref = read_yin_subnode(module->ctx, child, "text");
3722 if (!inc->ref) {
3723 goto error;
3724 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003725 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003726 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003727 goto error;
3728 }
3729 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003730
Radek Krejcie534c132016-11-23 13:32:31 +01003731 /* process extensions */
3732 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003733 /* some extensions may be already present from the substatements */
3734 reallocated = realloc(inc->ext, (c_ext + inc->ext_size) * sizeof *inc->ext);
3735 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003736 LOGMEM;
3737 goto error;
3738 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003739 inc->ext = reallocated;
3740
3741 /* init memory */
3742 memset(&inc->ext[inc->ext_size], 0, c_ext * sizeof *inc->ext);
3743
Radek Krejcie534c132016-11-23 13:32:31 +01003744 LY_TREE_FOR_SAFE(exts.child, next, child) {
3745 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003746 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 +01003747 inc->ext_size++;
3748 if (r) {
3749 goto error;
3750 }
3751 }
3752 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003753
Radek Krejcie534c132016-11-23 13:32:31 +01003754 GETVAL(value, yin, "module");
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003755 return lyp_check_include(submodule ? (struct lys_module *)submodule : module, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02003756
3757error:
3758
Radek Krejci83e3f5b2016-06-24 14:55:25 +02003759 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02003760}
3761
Michal Vasko0d343d12015-08-24 14:57:36 +02003762/* logs directly
3763 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003764 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02003765 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02003766 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003767 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003768static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01003769read_yin_common(struct lys_module *module, struct lys_node *parent, void *stmt, LYEXT_PAR stmt_type,
3770 struct lyxml_elem *xmlnode, int opt, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003771{
Radek Krejci07d0fb92017-01-13 14:11:05 +01003772 struct lys_node *node = stmt;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003773 const char *value;
3774 struct lyxml_elem *sub, *next;
3775 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003776
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003777 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003778 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003779 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003780
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003781 if (opt & OPT_IDENT) {
3782 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01003783 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003784 goto error;
3785 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003786 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003787 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003788
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003789 /* process local parameters */
3790 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003791 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003792 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003793 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02003794 continue;
3795 }
3796 if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejci6ff885d2017-01-03 14:06:22 +01003797 /* possibly an extension, keep the node for later processing, so skipping lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003798 continue;
3799 }
3800
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003801 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003802 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003803 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003804 goto error;
3805 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003806
Radek Krejci8d6b7422017-02-03 14:42:13 +01003807 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003808 goto error;
3809 }
3810
Radek Krejci1d82ef62015-08-07 14:44:40 +02003811 node->dsc = read_yin_subnode(ctx, sub, "text");
3812 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003813 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003814 }
3815 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003816 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003817 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003818 goto error;
3819 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003820
Radek Krejci8d6b7422017-02-03 14:42:13 +01003821 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003822 goto error;
3823 }
3824
Radek Krejci1d82ef62015-08-07 14:44:40 +02003825 node->ref = read_yin_subnode(ctx, sub, "text");
3826 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003827 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003828 }
3829 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003830 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003831 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003832 goto error;
3833 }
3834 GETVAL(value, sub, "value");
3835 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003836 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003837 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003838 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003839 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003840 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003841 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003842 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003843 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003844 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003845
Radek Krejci8d6b7422017-02-03 14:42:13 +01003846 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_STATUS, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003847 goto error;
3848 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003849 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3850 if (opt & OPT_CFG_PARSE) {
3851 if (node->flags & LYS_CONFIG_MASK) {
3852 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
3853 goto error;
3854 }
3855 GETVAL(value, sub, "value");
3856 if (!strcmp(value, "false")) {
3857 node->flags |= LYS_CONFIG_R;
3858 } else if (!strcmp(value, "true")) {
3859 node->flags |= LYS_CONFIG_W;
3860 } else {
3861 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3862 goto error;
3863 }
3864 node->flags |= LYS_CONFIG_SET;
Radek Krejci07d0fb92017-01-13 14:11:05 +01003865
Radek Krejci8d6b7422017-02-03 14:42:13 +01003866 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003867 goto error;
3868 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003869 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003870 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003871 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003872 continue;
3873 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003874 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003875 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003876
Michal Vaskoe022a562016-09-27 14:24:15 +02003877 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003878 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02003879 if (parent) {
3880 node->flags |= parent->flags & LYS_CONFIG_MASK;
3881 } else if (!parent) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003882 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003883 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003884 }
3885 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003886
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003887 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02003888
3889error:
3890
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003891 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003892}
3893
Michal Vasko0d343d12015-08-24 14:57:36 +02003894/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003895static struct lys_when *
Radek Krejci5323b492017-01-16 15:40:11 +01003896read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003897{
Radek Krejci76512572015-08-04 09:47:08 +02003898 struct lys_when *retval = NULL;
Radek Krejci5323b492017-01-16 15:40:11 +01003899 struct lyxml_elem *child, *next;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003900 const char *value;
3901
3902 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01003903 if (!retval) {
3904 LOGMEM;
3905 return NULL;
3906 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003907
3908 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01003909 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02003910 if (!retval->cond) {
3911 goto error;
3912 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003913
Radek Krejci5323b492017-01-16 15:40:11 +01003914 LY_TREE_FOR_SAFE(yin->child, next, child) {
3915 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003916 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003917 continue;
Radek Krejci5323b492017-01-16 15:40:11 +01003918 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3919 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01003920 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003921 goto error;
3922 }
3923 } else if (!strcmp(child->name, "description")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003924 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003925 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003926 goto error;
3927 }
Radek Krejci5323b492017-01-16 15:40:11 +01003928
Radek Krejci8d6b7422017-02-03 14:42:13 +01003929 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003930 goto error;
3931 }
3932
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003933 retval->dsc = read_yin_subnode(module->ctx, child, "text");
3934 if (!retval->dsc) {
3935 goto error;
3936 }
3937 } else if (!strcmp(child->name, "reference")) {
3938 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003939 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003940 goto error;
3941 }
Radek Krejci5323b492017-01-16 15:40:11 +01003942
Radek Krejci8d6b7422017-02-03 14:42:13 +01003943 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003944 goto error;
3945 }
3946
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003947 retval->ref = read_yin_subnode(module->ctx, child, "text");
3948 if (!retval->ref) {
3949 goto error;
3950 }
3951 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003952 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003953 goto error;
3954 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003955 }
3956
3957 return retval;
3958
3959error:
3960
Michal Vasko0308dd62015-10-07 09:14:40 +02003961 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003962 return NULL;
3963}
3964
Michal Vasko0d343d12015-08-24 14:57:36 +02003965/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003966static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01003967read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02003968 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02003969{
Michal Vasko29fc0182015-08-24 15:02:39 +02003970 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003971 struct lys_node_case *cs;
3972 struct lys_node *retval, *node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01003973 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01003974 void *reallocated;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003975
Radek Krejcie867c852015-08-27 09:52:34 +02003976 /* init */
3977 memset(&root, 0, sizeof root);
3978
Radek Krejci1d82ef62015-08-07 14:44:40 +02003979 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01003980 if (!cs) {
3981 LOGMEM;
3982 return NULL;
3983 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003984 cs->nodetype = LYS_CASE;
3985 cs->prev = (struct lys_node *)cs;
3986 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003987
Radek Krejci07d0fb92017-01-13 14:11:05 +01003988 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01003989 OPT_IDENT | OPT_MODULE | (!(options & LYS_PARSE_OPT_CFG_MASK) ? OPT_CFG_INHERIT : 0), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003990 goto error;
3991 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003992
Michal Vasko3e3228d2017-02-24 14:55:32 +01003993 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02003994
Michal Vasko3a0043f2015-08-12 12:11:30 +02003995 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003996 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003997 goto error;
3998 }
3999
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004000 /* process choice's specific children */
4001 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004002 if (strcmp(sub->ns->value, LY_NSYIN)) {
4003 /* extension */
4004 c_ext++;
4005 } else if (!strcmp(sub->name, "container") ||
Michal Vasko29fc0182015-08-24 15:02:39 +02004006 !strcmp(sub->name, "leaf-list") ||
4007 !strcmp(sub->name, "leaf") ||
4008 !strcmp(sub->name, "list") ||
4009 !strcmp(sub->name, "uses") ||
4010 !strcmp(sub->name, "choice") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01004011 !strcmp(sub->name, "anyxml") ||
4012 !strcmp(sub->name, "anydata")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02004013
Michal Vaskof3930de2015-10-22 12:03:59 +02004014 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02004015 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004016 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02004017 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004018 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004019 if (cs->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004020 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004021 goto error;
4022 }
4023
Radek Krejci5323b492017-01-16 15:40:11 +01004024 cs->when = read_yin_when(module, sub, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004025 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004026 goto error;
4027 }
Michal Vasko29fc0182015-08-24 15:02:39 +02004028
Michal Vasko345da0a2015-12-02 10:35:55 +01004029 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004030 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004031 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004032 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004033 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004034 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004035
Radek Krejci3cf9e222015-06-18 11:37:50 +02004036 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004037 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
4038 if (!cs->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004039 LOGMEM;
4040 goto error;
4041 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004042 }
Radek Krejcie534c132016-11-23 13:32:31 +01004043 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004044 /* some extensions may be already present from the substatements */
4045 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4046 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004047 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004048 goto error;
4049 }
Radek Krejci21c81652017-01-23 10:42:55 +01004050 retval->ext = reallocated;
4051
4052 /* init memory */
4053 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004054 }
Radek Krejci21c81652017-01-23 10:42:55 +01004055
Radek Krejcie534c132016-11-23 13:32:31 +01004056 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4057 if (strcmp(sub->ns->value, LY_NSYIN)) {
4058 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004059 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 +01004060 retval->ext_size++;
4061 if (ret) {
4062 goto error;
4063 }
4064 } else {
4065 /* if-feature */
4066 ret = fill_yin_iffeature(retval, 0, sub, &cs->iffeature[cs->iffeature_size], unres);
4067 cs->iffeature_size++;
4068 if (ret) {
4069 goto error;
4070 }
4071 }
4072 }
Radek Krejcib388c152015-06-04 17:03:03 +02004073
Michal Vasko29fc0182015-08-24 15:02:39 +02004074 /* last part - process data nodes */
4075 LY_TREE_FOR_SAFE(root.child, next, sub) {
4076 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004077 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004078 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004079 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004080 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004081 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004082 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004083 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004084 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004085 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004086 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004087 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004088 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004089 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004090 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004091 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004092 }
4093 if (!node) {
4094 goto error;
4095 }
4096
Michal Vasko345da0a2015-12-02 10:35:55 +01004097 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02004098 }
4099
Michal Vasko508a50d2016-09-07 14:50:33 +02004100 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01004101 if (cs->when) {
4102 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004103 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004104 goto error;
4105 }
4106 } else {
4107 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4108 goto error;
4109 }
4110 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004111 }
4112
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004113 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004114
4115error:
4116
Michal Vasko29fc0182015-08-24 15:02:39 +02004117 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004118 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02004119 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004120 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02004121
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004122 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004123}
4124
Michal Vasko0d343d12015-08-24 14:57:36 +02004125/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004126static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004127read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskoe022a562016-09-27 14:24:15 +02004128 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004129{
Radek Krejci629cdef2016-06-06 15:06:36 +02004130 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004131 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004132 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02004133 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02004134 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01004135 int f_mand = 0, c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004136 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004137
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004138 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01004139 if (!choice) {
4140 LOGMEM;
4141 return NULL;
4142 }
Radek Krejci76512572015-08-04 09:47:08 +02004143 choice->nodetype = LYS_CHOICE;
4144 choice->prev = (struct lys_node *)choice;
4145 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004146
Radek Krejci07d0fb92017-01-13 14:11:05 +01004147 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004148 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4149 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4150 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004151 goto error;
4152 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004153
Michal Vasko3e3228d2017-02-24 14:55:32 +01004154 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02004155
Michal Vasko3a0043f2015-08-12 12:11:30 +02004156 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004157 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004158 goto error;
4159 }
4160
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004161 /* process choice's specific children */
4162 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004163 if (strcmp(sub->ns->value, LY_NSYIN)) {
4164 /* extension */
4165 c_ext++;
4166 /* keep it for later processing, skip lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02004167 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004168 } else if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004169 if (!(node = read_yin_container(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004170 goto error;
4171 }
4172 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004173 if (!(node = read_yin_leaflist(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004174 goto error;
4175 }
4176 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004177 if (!(node = read_yin_leaf(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004178 goto error;
4179 }
4180 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004181 if (!(node = read_yin_list(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004182 goto error;
4183 }
4184 } else if (!strcmp(sub->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004185 if (!(node = read_yin_case(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004186 goto error;
4187 }
4188 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004189 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004190 goto error;
4191 }
4192 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004193 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004194 goto error;
4195 }
4196 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02004197 if (dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004198 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004199 goto error;
4200 }
Radek Krejci21c81652017-01-23 10:42:55 +01004201
Radek Krejci8d6b7422017-02-03 14:42:13 +01004202 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004203 goto error;
4204 }
4205
Radek Krejci629cdef2016-06-06 15:06:36 +02004206 dflt = sub;
4207 lyxml_unlink_elem(ctx, dflt, 0);
Radek Krejcif9a312c2016-06-06 15:14:30 +02004208 continue;
4209 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
4210
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004211 } else if (!strcmp(sub->name, "mandatory")) {
4212 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004213 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004214 goto error;
4215 }
4216 /* just checking the flags in leaf is not sufficient, we would allow
4217 * multiple mandatory statements with the "false" value
4218 */
4219 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004220
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004221 GETVAL(value, sub, "value");
4222 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004223 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004224 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004225 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004226 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004227 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004228 goto error;
4229 } /* else false is the default value, so we can ignore it */
Radek Krejci21c81652017-01-23 10:42:55 +01004230
Radek Krejci8d6b7422017-02-03 14:42:13 +01004231 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004232 goto error;
4233 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004234 } else if (!strcmp(sub->name, "when")) {
4235 if (choice->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004236 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004237 goto error;
4238 }
4239
Radek Krejci5323b492017-01-16 15:40:11 +01004240 choice->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004241 if (!choice->when) {
4242 goto error;
4243 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004244 } else if (!strcmp(sub->name, "if-feature")) {
4245 c_ftrs++;
4246
Michal Vasko345da0a2015-12-02 10:35:55 +01004247 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02004248 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02004249 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004250 if (!(node = read_yin_choice(module, retval, sub, options, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02004251 goto error;
4252 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004253 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004254 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004255 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004256 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004257
Radek Krejci1d82ef62015-08-07 14:44:40 +02004258 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01004259 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004260 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004261
Radek Krejci3cf9e222015-06-18 11:37:50 +02004262 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004263 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
4264 if (!choice->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004265 LOGMEM;
4266 goto error;
4267 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004268 }
Radek Krejcie534c132016-11-23 13:32:31 +01004269 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004270 /* some extensions may be already present from the substatements */
4271 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4272 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004273 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004274 goto error;
4275 }
Radek Krejci21c81652017-01-23 10:42:55 +01004276 retval->ext = reallocated;
4277
4278 /* init memory */
4279 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004280 }
4281
Radek Krejcie534c132016-11-23 13:32:31 +01004282 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4283 if (strcmp(sub->ns->value, LY_NSYIN)) {
4284 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004285 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 +01004286 retval->ext_size++;
4287 if (ret) {
4288 goto error;
4289 }
4290 } else {
4291 ret = fill_yin_iffeature(retval, 0, sub, &choice->iffeature[choice->iffeature_size], unres);
4292 choice->iffeature_size++;
4293 if (ret) {
4294 goto error;
4295 }
4296 }
4297 }
4298
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004299 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02004300 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004301 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "default", "choice");
Michal Vasko51e5c582017-01-19 14:16:39 +01004302 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004303 goto error;
4304 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004305
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004306 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02004307 if (dflt) {
4308 GETVAL(value, dflt, "value");
4309 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004310 goto error;
4311 }
Radek Krejci629cdef2016-06-06 15:06:36 +02004312 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004313 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004314
Michal Vasko508a50d2016-09-07 14:50:33 +02004315 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01004316 if (choice->when) {
4317 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004318 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004319 goto error;
4320 }
4321 } else {
4322 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4323 goto error;
4324 }
4325 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004326 }
4327
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004328 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004329
4330error:
4331
Radek Krejci629cdef2016-06-06 15:06:36 +02004332 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004333 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004334
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004335 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004336}
4337
Michal Vasko0d343d12015-08-24 14:57:36 +02004338/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004339static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004340read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004341 int options, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02004342{
Radek Krejci76512572015-08-04 09:47:08 +02004343 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02004344 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004345 struct lyxml_elem *sub, *next;
4346 const char *value;
4347 int r;
4348 int f_mand = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004349 int c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004350 void *reallocated;
Radek Krejci863c2852015-06-03 15:47:11 +02004351
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004352 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01004353 if (!anyxml) {
4354 LOGMEM;
4355 return NULL;
4356 }
Radek Krejcibf2abff2016-08-23 15:51:52 +02004357 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02004358 anyxml->prev = (struct lys_node *)anyxml;
4359 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02004360
Radek Krejci07d0fb92017-01-13 14:11:05 +01004361 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004362 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4363 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4364 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004365 goto error;
4366 }
Radek Krejci863c2852015-06-03 15:47:11 +02004367
Michal Vasko3e3228d2017-02-24 14:55:32 +01004368 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004369
Radek Krejcic189a952016-07-11 15:27:07 +02004370 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004371 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004372 goto error;
4373 }
4374
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004375 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004376 if (strcmp(sub->ns->value, LY_NSYIN)) {
4377 /* extension */
4378 c_ext++;
4379 } else if (!strcmp(sub->name, "mandatory")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004380 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004381 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004382 goto error;
4383 }
4384 /* just checking the flags in leaf is not sufficient, we would allow
4385 * multiple mandatory statements with the "false" value
4386 */
4387 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02004388
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004389 GETVAL(value, sub, "value");
4390 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004391 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004392 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004393 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004394 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004395 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004396 goto error;
4397 }
4398 /* else false is the default value, so we can ignore it */
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004399
Radek Krejci8d6b7422017-02-03 14:42:13 +01004400 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004401 goto error;
4402 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004403 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004404 } else if (!strcmp(sub->name, "when")) {
4405 if (anyxml->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004406 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004407 goto error;
4408 }
4409
Radek Krejci5323b492017-01-16 15:40:11 +01004410 anyxml->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004411 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004412 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004413 goto error;
4414 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004415 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004416 } else if (!strcmp(sub->name, "must")) {
4417 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004418 } else if (!strcmp(sub->name, "if-feature")) {
4419 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02004420
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004421 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004422 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004423 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004424 }
4425 }
Radek Krejci863c2852015-06-03 15:47:11 +02004426
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004427 /* middle part - process nodes with cardinality of 0..n */
4428 if (c_must) {
4429 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004430 if (!anyxml->must) {
4431 LOGMEM;
4432 goto error;
4433 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004434 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004435 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004436 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
4437 if (!anyxml->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004438 LOGMEM;
4439 goto error;
4440 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004441 }
Radek Krejcie534c132016-11-23 13:32:31 +01004442 if (c_ext) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004443 /* some extensions may be already present from the substatements */
4444 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4445 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004446 LOGMEM;
4447 goto error;
4448 }
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004449 retval->ext = reallocated;
4450
4451 /* init memory */
4452 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004453 }
Radek Krejci863c2852015-06-03 15:47:11 +02004454
Radek Krejcie534c132016-11-23 13:32:31 +01004455 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4456 if (strcmp(sub->ns->value, LY_NSYIN)) {
4457 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004458 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 +01004459 retval->ext_size++;
4460 if (r) {
4461 goto error;
4462 }
4463 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004464 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004465 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004466 if (r) {
4467 goto error;
4468 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004469 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004470 r = fill_yin_iffeature(retval, 0, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004471 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004472 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004473 goto error;
4474 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004475 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004476 }
Radek Krejci863c2852015-06-03 15:47:11 +02004477
Michal Vasko508a50d2016-09-07 14:50:33 +02004478 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01004479 if (anyxml->when || anyxml->must) {
4480 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004481 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004482 goto error;
4483 }
4484 } else {
4485 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4486 goto error;
4487 }
4488 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004489 }
4490
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004491 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02004492
4493error:
4494
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004495 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02004496
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004497 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02004498}
4499
Michal Vasko0d343d12015-08-24 14:57:36 +02004500/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004501static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004502read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004503 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004504{
Radek Krejci76512572015-08-04 09:47:08 +02004505 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004506 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004507 struct lyxml_elem *sub, *next;
4508 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01004509 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004510 int c_must = 0, c_ftrs = 0, f_mand = 0, c_ext = 0;
Radek Krejcifccd1442017-01-16 10:26:57 +01004511 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004512
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004513 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01004514 if (!leaf) {
4515 LOGMEM;
4516 return NULL;
4517 }
Radek Krejci76512572015-08-04 09:47:08 +02004518 leaf->nodetype = LYS_LEAF;
4519 leaf->prev = (struct lys_node *)leaf;
4520 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004521
Radek Krejci07d0fb92017-01-13 14:11:05 +01004522 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004523 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4524 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4525 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004526 goto error;
4527 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004528
Michal Vasko3e3228d2017-02-24 14:55:32 +01004529 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004530
Radek Krejcic189a952016-07-11 15:27:07 +02004531 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004532 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004533 goto error;
4534 }
4535
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004536 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004537 if (strcmp(sub->ns->value, LY_NSYIN)) {
4538 /* extension */
4539 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004540 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004541 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004542 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004543 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004544 goto error;
4545 }
Michal Vasko88c29542015-11-27 14:57:53 +01004546 /* HACK for unres */
4547 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004548 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004549 /* postpone type resolution when if-feature parsing is done since we need
4550 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004551 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004552 } else if (!strcmp(sub->name, "default")) {
4553 if (leaf->dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004554 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004555 goto error;
4556 }
4557 GETVAL(value, sub, "value");
4558 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci1abcdae2017-01-18 14:14:18 +01004559
Radek Krejci8d6b7422017-02-03 14:42:13 +01004560 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci1abcdae2017-01-18 14:14:18 +01004561 goto error;
4562 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004563 } else if (!strcmp(sub->name, "units")) {
4564 if (leaf->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004565 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004566 goto error;
4567 }
4568 GETVAL(value, sub, "name");
4569 leaf->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004570
Radek Krejci8d6b7422017-02-03 14:42:13 +01004571 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004572 goto error;
4573 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004574 } else if (!strcmp(sub->name, "mandatory")) {
4575 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004576 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004577 goto error;
4578 }
4579 /* just checking the flags in leaf is not sufficient, we would allow
4580 * multiple mandatory statements with the "false" value
4581 */
4582 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02004583
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004584 GETVAL(value, sub, "value");
4585 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004586 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004587 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004588 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004589 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004590 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004591 goto error;
4592 } /* else false is the default value, so we can ignore it */
Radek Krejcifccd1442017-01-16 10:26:57 +01004593
Radek Krejci8d6b7422017-02-03 14:42:13 +01004594 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004595 goto error;
4596 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004597 } else if (!strcmp(sub->name, "when")) {
4598 if (leaf->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004599 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004600 goto error;
4601 }
4602
Radek Krejci5323b492017-01-16 15:40:11 +01004603 leaf->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004604 if (!leaf->when) {
4605 goto error;
4606 }
4607
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004608 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02004609 c_must++;
4610 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004611 } else if (!strcmp(sub->name, "if-feature")) {
4612 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004613 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004614
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004615 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004616 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004617 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004618 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004619
Michal Vasko88c29542015-11-27 14:57:53 +01004620 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004621 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004622
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004623 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004624 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004625 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004626 goto error;
4627 }
Michal Vasko478c4652016-07-21 12:55:01 +02004628 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004629 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "mandatory", "leaf");
Michal Vasko51e5c582017-01-19 14:16:39 +01004630 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL,
Michal Vasko478c4652016-07-21 12:55:01 +02004631 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
4632 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004633 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004634
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004635 /* middle part - process nodes with cardinality of 0..n */
4636 if (c_must) {
4637 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004638 if (!leaf->must) {
4639 LOGMEM;
4640 goto error;
4641 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004642 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004643 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004644 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
4645 if (!leaf->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004646 LOGMEM;
4647 goto error;
4648 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004649 }
Radek Krejcie534c132016-11-23 13:32:31 +01004650 if (c_ext) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004651 /* some extensions may be already present from the substatements */
4652 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4653 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004654 LOGMEM;
4655 goto error;
4656 }
Radek Krejcifccd1442017-01-16 10:26:57 +01004657 retval->ext = reallocated;
4658
4659 /* init memory */
4660 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004661 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004662
Radek Krejcie534c132016-11-23 13:32:31 +01004663 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4664 if (strcmp(sub->ns->value, LY_NSYIN)) {
4665 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004666 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 +01004667 retval->ext_size++;
4668 if (r) {
4669 goto error;
4670 }
4671 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004672 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004673 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004674 if (r) {
4675 goto error;
4676 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004677 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004678 r = fill_yin_iffeature(retval, 0, sub, &leaf->iffeature[leaf->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004679 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004680 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004681 goto error;
4682 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004683 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004684 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004685
Radek Krejcicbb473e2016-09-16 14:48:32 +02004686 /* finalize type parsing */
4687 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
4688 leaf->type.der = NULL;
4689 goto error;
4690 }
4691
4692 /* check default value (if not defined, there still could be some restrictions
4693 * that need to be checked against a default value from a derived type) */
Radek Krejciab08f0f2017-03-09 16:37:15 +01004694 if (!(options & LYS_PARSE_OPT_INGRP) &&
4695 (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT,
4696 (struct lys_node *)(&leaf->dflt)) == -1)) {
Radek Krejcicbb473e2016-09-16 14:48:32 +02004697 goto error;
4698 }
4699
Michal Vasko508a50d2016-09-07 14:50:33 +02004700 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01004701 if (leaf->when || leaf->must) {
4702 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004703 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004704 goto error;
4705 }
4706 } else {
4707 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4708 goto error;
4709 }
4710 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004711 }
4712
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004713 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004714
4715error:
4716
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004717 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004718
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004719 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004720}
4721
Michal Vasko0d343d12015-08-24 14:57:36 +02004722/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004723static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004724read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004725 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004726{
Radek Krejci76512572015-08-04 09:47:08 +02004727 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004728 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004729 struct lyxml_elem *sub, *next;
4730 const char *value;
4731 char *endptr;
4732 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004733 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004734 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004735 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejci5323b492017-01-16 15:40:11 +01004736 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004737
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004738 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01004739 if (!llist) {
4740 LOGMEM;
4741 return NULL;
4742 }
Radek Krejci76512572015-08-04 09:47:08 +02004743 llist->nodetype = LYS_LEAFLIST;
4744 llist->prev = (struct lys_node *)llist;
4745 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004746
Radek Krejci07d0fb92017-01-13 14:11:05 +01004747 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004748 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4749 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4750 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004751 goto error;
4752 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004753
Michal Vasko3e3228d2017-02-24 14:55:32 +01004754 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004755
Radek Krejcic189a952016-07-11 15:27:07 +02004756 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004757 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004758 goto error;
4759 }
4760
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004761 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004762 if (strcmp(sub->ns->value, LY_NSYIN)) {
4763 /* extension */
4764 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004765 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004766 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004767 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004768 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004769 goto error;
4770 }
Michal Vasko88c29542015-11-27 14:57:53 +01004771 /* HACK for unres */
4772 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004773 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004774 /* postpone type resolution when if-feature parsing is done since we need
4775 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004776 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004777 } else if (!strcmp(sub->name, "units")) {
4778 if (llist->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004779 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004780 goto error;
4781 }
4782 GETVAL(value, sub, "name");
4783 llist->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004784
Radek Krejci8d6b7422017-02-03 14:42:13 +01004785 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004786 goto error;
4787 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004788 } else if (!strcmp(sub->name, "ordered-by")) {
4789 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004790 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004791 goto error;
4792 }
4793 /* just checking the flags in llist is not sufficient, we would
4794 * allow multiple ordered-by statements with the "system" value
4795 */
4796 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004797
Radek Krejci1574a8d2015-08-03 14:16:52 +02004798 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004799 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4800 * state data
4801 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004802 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004803 continue;
4804 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004805
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004806 GETVAL(value, sub, "value");
4807 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004808 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004809 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004810 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004811 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02004812 } /* else system is the default value, so we can ignore it */
4813
Radek Krejci8d6b7422017-02-03 14:42:13 +01004814 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004815 goto error;
4816 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004817 } else if (!strcmp(sub->name, "must")) {
4818 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02004819 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004820 } else if (!strcmp(sub->name, "if-feature")) {
4821 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004822 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02004823 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004824 /* read the default's extension instances */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004825 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, c_dflt, unres)) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004826 goto error;
4827 }
4828
Radek Krejcid5a5c282016-08-15 15:38:08 +02004829 c_dflt++;
4830 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004831
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004832 } else if (!strcmp(sub->name, "min-elements")) {
4833 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004834 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004835 goto error;
4836 }
4837 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004838
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004839 GETVAL(value, sub, "value");
4840 while (isspace(value[0])) {
4841 value++;
4842 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004843
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004844 /* convert it to uint32_t */
4845 errno = 0;
4846 endptr = NULL;
4847 val = strtoul(value, &endptr, 10);
4848 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004849 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004850 goto error;
4851 }
4852 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004853 if (llist->max && (llist->min > llist->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004854 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004855 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004856 goto error;
4857 }
Radek Krejci5323b492017-01-16 15:40:11 +01004858
Radek Krejci8d6b7422017-02-03 14:42:13 +01004859 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004860 goto error;
4861 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004862 } else if (!strcmp(sub->name, "max-elements")) {
4863 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004864 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004865 goto error;
4866 }
4867 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004868
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004869 GETVAL(value, sub, "value");
4870 while (isspace(value[0])) {
4871 value++;
4872 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004873
Radek Krejci0d7b2472016-02-12 11:11:03 +01004874 if (!strcmp(value, "unbounded")) {
4875 llist->max = 0;
4876 } else {
4877 /* convert it to uint32_t */
4878 errno = 0;
4879 endptr = NULL;
4880 val = strtoul(value, &endptr, 10);
4881 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004882 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004883 goto error;
4884 }
4885 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004886 if (llist->min > llist->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004887 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004888 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004889 goto error;
4890 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004891 }
Radek Krejci5323b492017-01-16 15:40:11 +01004892
Radek Krejci8d6b7422017-02-03 14:42:13 +01004893 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004894 goto error;
4895 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004896 } else if (!strcmp(sub->name, "when")) {
4897 if (llist->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004898 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004899 goto error;
4900 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004901
Radek Krejci5323b492017-01-16 15:40:11 +01004902 llist->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004903 if (!llist->when) {
4904 goto error;
4905 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004906 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004907 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004908 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004909 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004910
Michal Vasko88c29542015-11-27 14:57:53 +01004911 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004912 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004913
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004914 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004915 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004916 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004917 goto error;
4918 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004919
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004920 /* middle part - process nodes with cardinality of 0..n */
4921 if (c_must) {
4922 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004923 if (!llist->must) {
4924 LOGMEM;
4925 goto error;
4926 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004927 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004928 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004929 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
4930 if (!llist->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004931 LOGMEM;
4932 goto error;
4933 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004934 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004935 if (c_dflt) {
4936 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
4937 if (!llist->dflt) {
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004938 LOGMEM;
4939 goto error;
4940 }
4941 }
Radek Krejcie534c132016-11-23 13:32:31 +01004942 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01004943 /* some extensions may be already present from the substatements */
4944 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4945 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004946 LOGMEM;
4947 goto error;
4948 }
Radek Krejci5323b492017-01-16 15:40:11 +01004949 retval->ext = reallocated;
4950
4951 /* init memory */
4952 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004953 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004954
Radek Krejcie534c132016-11-23 13:32:31 +01004955 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4956 if (strcmp(sub->ns->value, LY_NSYIN)) {
4957 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004958 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 +01004959 retval->ext_size++;
4960 if (r) {
4961 goto error;
4962 }
4963 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004964 r = fill_yin_must(module, sub, &llist->must[llist->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004965 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004966 if (r) {
4967 goto error;
4968 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004969 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004970 r = fill_yin_iffeature(retval, 0, sub, &llist->iffeature[llist->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004971 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004972 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004973 goto error;
4974 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004975 } else if (!strcmp(sub->name, "default")) {
4976 GETVAL(value, sub, "value");
4977
Radek Krejciac1a52c2016-09-15 14:42:40 +02004978 /* check for duplicity in case of configuration data,
4979 * in case of status data duplicities are allowed */
4980 if (llist->flags & LYS_CONFIG_W) {
4981 for (r = 0; r < llist->dflt_size; r++) {
4982 if (ly_strequal(llist->dflt[r], value, 1)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004983 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, "default");
Michal Vasko51e5c582017-01-19 14:16:39 +01004984 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "Duplicated default value \"%s\".", value);
Radek Krejciac1a52c2016-09-15 14:42:40 +02004985 goto error;
4986 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004987 }
4988 }
4989 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004990 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004991 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004992
Radek Krejcicbb473e2016-09-16 14:48:32 +02004993 /* finalize type parsing */
4994 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
4995 llist->type.der = NULL;
4996 goto error;
4997 }
4998
Radek Krejcid5a5c282016-08-15 15:38:08 +02004999 if (llist->dflt_size && llist->min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005000 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "min-elements", "leaf-list");
Michal Vasko51e5c582017-01-19 14:16:39 +01005001 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02005002 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
5003 goto error;
5004 }
5005
5006 /* check default value (if not defined, there still could be some restrictions
5007 * that need to be checked against a default value from a derived type) */
5008 for (r = 0; r < llist->dflt_size; r++) {
Radek Krejciab08f0f2017-03-09 16:37:15 +01005009 if (!(options & LYS_PARSE_OPT_INGRP) &&
5010 (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
5011 (struct lys_node *)(&llist->dflt[r])) == -1)) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02005012 goto error;
Radek Krejci25d782a2015-05-22 15:03:23 +02005013 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005014 }
5015
Michal Vasko508a50d2016-09-07 14:50:33 +02005016 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01005017 if (llist->when || llist->must) {
5018 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005019 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005020 goto error;
5021 }
5022 } else {
5023 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5024 goto error;
5025 }
5026 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005027 }
5028
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005029 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005030
5031error:
5032
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005033 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005034
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005035 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005036}
5037
Michal Vasko0d343d12015-08-24 14:57:36 +02005038/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005039static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005040read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005041 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005042{
Radek Krejci1d82ef62015-08-07 14:44:40 +02005043 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02005044 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005045 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01005046 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005047 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005048 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejci5c08a992016-11-02 13:30:04 +01005049 const char *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005050 char *auxs;
5051 unsigned long val;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005052 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005053
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005054 /* init */
5055 memset(&root, 0, sizeof root);
5056 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02005057
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005058 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01005059 if (!list) {
5060 LOGMEM;
5061 return NULL;
5062 }
Radek Krejci76512572015-08-04 09:47:08 +02005063 list->nodetype = LYS_LIST;
5064 list->prev = (struct lys_node *)list;
5065 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005066
Radek Krejci07d0fb92017-01-13 14:11:05 +01005067 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005068 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
5069 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
5070 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005071 goto error;
5072 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005073
Michal Vasko3e3228d2017-02-24 14:55:32 +01005074 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005075
Radek Krejcic189a952016-07-11 15:27:07 +02005076 /* insert the node into the schema tree */
5077 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5078 goto error;
5079 }
5080
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005081 /* process list's specific children */
5082 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005083 if (strcmp(sub->ns->value, LY_NSYIN)) {
5084 /* extension */
5085 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005086 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02005087
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005088 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005089 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005090 !strcmp(sub->name, "leaf-list") ||
5091 !strcmp(sub->name, "leaf") ||
5092 !strcmp(sub->name, "list") ||
5093 !strcmp(sub->name, "choice") ||
5094 !strcmp(sub->name, "uses") ||
5095 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005096 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005097 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005098 !strcmp(sub->name, "action") ||
5099 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005100 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005101 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005102
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005103 /* array counters */
5104 } else if (!strcmp(sub->name, "key")) {
5105 /* check cardinality 0..1 */
5106 if (list->keys_size) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005107 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005108 goto error;
5109 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005110
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005111 /* count the number of keys */
5112 GETVAL(value, sub, "value");
Radek Krejci5c08a992016-11-02 13:30:04 +01005113 list->keys_str = lydict_insert(module->ctx, value, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005114 while ((value = strpbrk(value, " \t\n"))) {
5115 list->keys_size++;
5116 while (isspace(*value)) {
5117 value++;
5118 }
5119 }
5120 list->keys_size++;
5121 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01005122 if (!list->keys) {
5123 LOGMEM;
5124 goto error;
5125 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005126
Radek Krejci8d6b7422017-02-03 14:42:13 +01005127 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_KEY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005128 goto error;
5129 }
5130 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005131 } else if (!strcmp(sub->name, "unique")) {
5132 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005133 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005134 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005135 } else if (!strcmp(sub->name, "typedef")) {
5136 c_tpdf++;
5137 } else if (!strcmp(sub->name, "must")) {
5138 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005139 } else if (!strcmp(sub->name, "if-feature")) {
5140 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02005141
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005142 /* optional stetments */
5143 } else if (!strcmp(sub->name, "ordered-by")) {
5144 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005145 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005146 goto error;
5147 }
5148 /* just checking the flags in llist is not sufficient, we would
5149 * allow multiple ordered-by statements with the "system" value
5150 */
5151 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005152
Radek Krejci1574a8d2015-08-03 14:16:52 +02005153 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005154 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
5155 * state data
5156 */
Michal Vasko345da0a2015-12-02 10:35:55 +01005157 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005158 continue;
5159 }
Radek Krejci345ad742015-06-03 11:04:18 +02005160
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005161 GETVAL(value, sub, "value");
5162 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02005163 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005164 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005165 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005166 goto error;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005167 } /* else system is the default value, so we can ignore it */
5168
Radek Krejci8d6b7422017-02-03 14:42:13 +01005169 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005170 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005171 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005172 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005173 } else if (!strcmp(sub->name, "min-elements")) {
5174 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005175 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005176 goto error;
5177 }
5178 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005180 GETVAL(value, sub, "value");
5181 while (isspace(value[0])) {
5182 value++;
5183 }
Radek Krejci345ad742015-06-03 11:04:18 +02005184
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005185 /* convert it to uint32_t */
5186 errno = 0;
5187 auxs = NULL;
5188 val = strtoul(value, &auxs, 10);
5189 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005190 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005191 goto error;
5192 }
5193 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005194 if (list->max && (list->min > list->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005195 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01005196 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005197 lyxml_free(module->ctx, sub);
5198 goto error;
5199 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005200 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005201 goto error;
5202 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005203 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005204 } else if (!strcmp(sub->name, "max-elements")) {
5205 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005206 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005207 goto error;
5208 }
5209 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005210
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005211 GETVAL(value, sub, "value");
5212 while (isspace(value[0])) {
5213 value++;
5214 }
Radek Krejci345ad742015-06-03 11:04:18 +02005215
Radek Krejci0d7b2472016-02-12 11:11:03 +01005216 if (!strcmp(value, "unbounded")) {
5217 list->max = 0;;
5218 } else {
5219 /* convert it to uint32_t */
5220 errno = 0;
5221 auxs = NULL;
5222 val = strtoul(value, &auxs, 10);
5223 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005224 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01005225 goto error;
5226 }
5227 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005228 if (list->min > list->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005229 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01005230 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005231 goto error;
5232 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005233 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005234 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005235 goto error;
5236 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005237 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005238 } else if (!strcmp(sub->name, "when")) {
5239 if (list->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005240 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005241 goto error;
5242 }
5243
Radek Krejci5323b492017-01-16 15:40:11 +01005244 list->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005245 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005246 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005247 goto error;
5248 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005249 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005250 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005251 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005252 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005253 }
5254 }
Radek Krejci345ad742015-06-03 11:04:18 +02005255
Michal Vaskoe022a562016-09-27 14:24:15 +02005256 /* check - if list is configuration, key statement is mandatory
5257 * (but only if we are not in a grouping or augment, then the check is deferred) */
Radek Krejcif95b6292017-02-13 15:57:37 +01005258 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); node = node->parent);
Radek Krejci5c08a992016-11-02 13:30:04 +01005259 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys_str) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005260 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005261 goto error;
5262 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005263
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005264 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5265 if (c_tpdf) {
5266 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005267 if (!list->tpdf) {
5268 LOGMEM;
5269 goto error;
5270 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005271 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005272 if (c_must) {
5273 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01005274 if (!list->must) {
5275 LOGMEM;
5276 goto error;
5277 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005278 }
5279 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005280 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
5281 if (!list->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005282 LOGMEM;
5283 goto error;
5284 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005285 }
Radek Krejcie534c132016-11-23 13:32:31 +01005286 if (c_ext) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005287 /* some extensions may be already present from the substatements */
5288 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5289 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005290 LOGMEM;
5291 goto error;
5292 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005293 retval->ext = reallocated;
5294
5295 /* init memory */
5296 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005297 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005298
Radek Krejcie534c132016-11-23 13:32:31 +01005299 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5300 if (strcmp(sub->ns->value, LY_NSYIN)) {
5301 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005302 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 +01005303 retval->ext_size++;
5304 if (r) {
5305 goto error;
5306 }
5307 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005308 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
5309 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005310 if (r) {
5311 goto error;
5312 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005313 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005314 r = fill_yin_iffeature(retval, 0, sub, &list->iffeature[list->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005315 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005316 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005317 goto error;
5318 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005319 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005320 r = fill_yin_must(module, sub, &list->must[list->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005321 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005322 if (r) {
5323 goto error;
5324 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005325 }
5326 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005327
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005328 /* last part - process data nodes */
5329 LY_TREE_FOR_SAFE(root.child, next, sub) {
5330 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005331 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005332 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005333 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005334 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005335 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005336 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005337 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005338 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005339 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005340 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005341 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005342 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005343 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005344 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005345 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005346 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005347 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005348 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005349 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005350 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005351 node = read_yin_notif(module, retval, sub, options, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005352 } else {
5353 LOGINT;
5354 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005355 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005356 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005357 goto error;
5358 }
Radek Krejci73adb602015-07-02 18:07:40 +02005359
Michal Vasko345da0a2015-12-02 10:35:55 +01005360 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005361 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005362
Radek Krejci5c08a992016-11-02 13:30:04 +01005363 if (list->keys_str) {
5364 /* check that we are not in grouping */
5365 for (node = parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
5366 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01005367 goto error;
5368 }
5369 } /* 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 +02005370
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005371 /* process unique statements */
5372 if (c_uniq) {
5373 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01005374 if (!list->unique) {
5375 LOGMEM;
5376 goto error;
5377 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005378
Radek Krejci461efb92016-02-12 15:52:18 +01005379 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
5380 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
5381 list->unique_size++;
5382 if (r) {
5383 goto error;
5384 }
5385
Radek Krejci8d6b7422017-02-03 14:42:13 +01005386 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub,
Radek Krejcie36d7c72017-01-17 16:12:30 +01005387 LYEXT_SUBSTMT_UNIQUE, list->unique_size - 1, unres)) {
5388 goto error;
5389 }
Radek Krejci461efb92016-02-12 15:52:18 +01005390 lyxml_free(module->ctx, sub);
5391 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005392 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005393
Michal Vasko508a50d2016-09-07 14:50:33 +02005394 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01005395 if (list->when || list->must) {
5396 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005397 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005398 goto error;
5399 }
5400 } else {
5401 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5402 goto error;
5403 }
5404 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005405 }
5406
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005407 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005408
5409error:
5410
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005411 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005412 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005413 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005414 }
5415 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005416 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005417 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005418
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005419 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005420}
5421
Michal Vasko0d343d12015-08-24 14:57:36 +02005422/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005423static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005424read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005425 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005426{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005427 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005428 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005429 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005430 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005431 const char *value;
Radek Krejci07d0fb92017-01-13 14:11:05 +01005432 void *reallocated;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005433 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005434 int c_tpdf = 0, c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005435
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005436 /* init */
5437 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005438
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005439 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01005440 if (!cont) {
5441 LOGMEM;
5442 return NULL;
5443 }
Radek Krejci76512572015-08-04 09:47:08 +02005444 cont->nodetype = LYS_CONTAINER;
5445 cont->prev = (struct lys_node *)cont;
5446 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005447
Radek Krejci07d0fb92017-01-13 14:11:05 +01005448 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005449 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
5450 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
5451 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005452 goto error;
5453 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005454
Michal Vasko3e3228d2017-02-24 14:55:32 +01005455 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005456
Radek Krejcic189a952016-07-11 15:27:07 +02005457 /* insert the node into the schema tree */
5458 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5459 goto error;
5460 }
5461
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005462 /* process container's specific children */
5463 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005464 if (strcmp(sub->ns->value, LY_NSYIN)) {
5465 /* extension */
5466 c_ext++;
5467 } else if (!strcmp(sub->name, "presence")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005468 if (cont->presence) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005469 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005470 goto error;
5471 }
5472 GETVAL(value, sub, "value");
5473 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02005474
Radek Krejci8d6b7422017-02-03 14:42:13 +01005475 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005476 goto error;
5477 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005478 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005479 } else if (!strcmp(sub->name, "when")) {
5480 if (cont->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005481 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005482 goto error;
5483 }
5484
Radek Krejci5323b492017-01-16 15:40:11 +01005485 cont->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005486 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005487 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005488 goto error;
5489 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005490 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02005491
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005492 /* data statements */
5493 } else if (!strcmp(sub->name, "container") ||
5494 !strcmp(sub->name, "leaf-list") ||
5495 !strcmp(sub->name, "leaf") ||
5496 !strcmp(sub->name, "list") ||
5497 !strcmp(sub->name, "choice") ||
5498 !strcmp(sub->name, "uses") ||
5499 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005500 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005501 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005502 !strcmp(sub->name, "action") ||
5503 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005504 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005505 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005506
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005507 /* array counters */
5508 } else if (!strcmp(sub->name, "typedef")) {
5509 c_tpdf++;
5510 } else if (!strcmp(sub->name, "must")) {
5511 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005512 } else if (!strcmp(sub->name, "if-feature")) {
5513 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005514 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005515 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005516 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005517 }
5518 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005519
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005520 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5521 if (c_tpdf) {
5522 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005523 if (!cont->tpdf) {
5524 LOGMEM;
5525 goto error;
5526 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005527 }
5528 if (c_must) {
5529 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01005530 if (!cont->must) {
5531 LOGMEM;
5532 goto error;
5533 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005534 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005535 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005536 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
5537 if (!cont->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005538 LOGMEM;
5539 goto error;
5540 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005541 }
Radek Krejcie534c132016-11-23 13:32:31 +01005542 if (c_ext) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01005543 /* some extensions may be already present from the substatements */
5544 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5545 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005546 LOGMEM;
5547 goto error;
5548 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01005549 retval->ext = reallocated;
5550
5551 /* init memory */
5552 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005553 }
Radek Krejci800af702015-06-02 13:46:01 +02005554
Radek Krejcie534c132016-11-23 13:32:31 +01005555 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5556 if (strcmp(sub->ns->value, LY_NSYIN)) {
5557 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005558 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 +01005559 retval->ext_size++;
5560 if (r) {
5561 goto error;
5562 }
5563 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005564 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
5565 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005566 if (r) {
5567 goto error;
5568 }
5569 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005570 r = fill_yin_must(module, sub, &cont->must[cont->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005571 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005572 if (r) {
5573 goto error;
5574 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005575 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005576 r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005577 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005578 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005579 goto error;
5580 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005581 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005582 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005583
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005584 /* last part - process data nodes */
5585 LY_TREE_FOR_SAFE(root.child, next, sub) {
5586 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005587 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005588 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005589 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005590 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005591 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005592 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005593 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005594 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005595 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005596 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005597 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005598 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005599 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005600 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005601 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005602 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005603 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005604 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005605 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005606 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005607 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005608 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005609 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005610 goto error;
5611 }
Radek Krejci73adb602015-07-02 18:07:40 +02005612
Michal Vasko345da0a2015-12-02 10:35:55 +01005613 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005614 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005615
Michal Vasko508a50d2016-09-07 14:50:33 +02005616 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01005617 if (cont->when || cont->must) {
5618 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005619 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005620 goto error;
5621 }
5622 } else {
5623 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5624 goto error;
5625 }
5626 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005627 }
5628
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005629 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005630
5631error:
5632
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005633 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005634 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005635 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005636 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005638 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005639}
5640
Michal Vasko0d343d12015-08-24 14:57:36 +02005641/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005642static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005643read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005644 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005645{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005646 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005647 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005648 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005649 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005650 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005651 int c_tpdf = 0, c_ext = 0;
Radek Krejcifdc0d702017-01-23 15:58:38 +01005652 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005653
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005654 /* init */
5655 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005657 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01005658 if (!grp) {
5659 LOGMEM;
5660 return NULL;
5661 }
Radek Krejci76512572015-08-04 09:47:08 +02005662 grp->nodetype = LYS_GROUPING;
5663 grp->prev = (struct lys_node *)grp;
5664 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005665
Radek Krejci07d0fb92017-01-13 14:11:05 +01005666 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE , unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005667 goto error;
5668 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005669
Michal Vasko3e3228d2017-02-24 14:55:32 +01005670 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005671
Radek Krejcic189a952016-07-11 15:27:07 +02005672 /* insert the node into the schema tree */
5673 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5674 goto error;
5675 }
5676
Radek Krejci1d82ef62015-08-07 14:44:40 +02005677 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005678 if (strcmp(sub->ns->value, LY_NSYIN)) {
5679 /* extension */
5680 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005681
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005682 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005683 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005684 !strcmp(sub->name, "leaf-list") ||
5685 !strcmp(sub->name, "leaf") ||
5686 !strcmp(sub->name, "list") ||
5687 !strcmp(sub->name, "choice") ||
5688 !strcmp(sub->name, "uses") ||
5689 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005690 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005691 !strcmp(sub->name, "anydata") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02005692 !strcmp(sub->name, "action") ||
5693 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005694 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005695 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005696
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005697 /* array counters */
5698 } else if (!strcmp(sub->name, "typedef")) {
5699 c_tpdf++;
5700 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005701 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005702 goto error;
5703 }
5704 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005705
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005706 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5707 if (c_tpdf) {
5708 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005709 if (!grp->tpdf) {
5710 LOGMEM;
5711 goto error;
5712 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005713 }
Radek Krejcie534c132016-11-23 13:32:31 +01005714 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01005715 /* some extensions may be already present from the substatements */
5716 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5717 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005718 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02005719 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005720 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01005721 retval->ext = reallocated;
5722
5723 /* init memory */
5724 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005725 }
Radek Krejcie534c132016-11-23 13:32:31 +01005726 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5727 if (strcmp(sub->ns->value, LY_NSYIN)) {
5728 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005729 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 +01005730 retval->ext_size++;
5731 if (r) {
5732 goto error;
5733 }
5734 } else {
5735 /* typedef */
5736 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
5737 grp->tpdf_size++;
5738 if (r) {
5739 goto error;
5740 }
5741 }
5742 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005743
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005744 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02005745 if (!root.child) {
5746 LOGWRN("Grouping \"%s\" without children.", retval->name);
5747 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01005748 options |= LYS_PARSE_OPT_INGRP;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005749 LY_TREE_FOR_SAFE(root.child, next, sub) {
5750 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005751 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005752 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005753 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005754 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005755 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005756 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005757 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005758 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005759 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005760 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005761 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005762 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005763 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005764 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005765 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005766 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005767 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005768 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005769 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02005770 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005771 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005772 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005773 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005774 goto error;
5775 }
Radek Krejci73adb602015-07-02 18:07:40 +02005776
Michal Vasko345da0a2015-12-02 10:35:55 +01005777 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005778 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005779
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005780 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005781
5782error:
5783
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005784 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005785 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005786 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005787 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005788
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005789 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005790}
5791
Michal Vasko0d343d12015-08-24 14:57:36 +02005792/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005793static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005794read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005795 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005796{
Radek Krejcie0674f82015-06-15 13:58:51 +02005797 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005798 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02005799 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02005800 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005801 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005802 int c_tpdf = 0, c_must = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005803
Radek Krejcie0674f82015-06-15 13:58:51 +02005804 /* init */
5805 memset(&root, 0, sizeof root);
5806
Michal Vasko38d01f72015-06-15 09:41:06 +02005807 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01005808 if (!inout) {
5809 LOGMEM;
5810 return NULL;
5811 }
Radek Krejci6acc8012015-08-13 09:07:04 +02005812 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005813
5814 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02005815 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005816 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005817 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02005818 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005819 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005820 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02005821 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02005822 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02005823 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005824 }
5825
Radek Krejci76512572015-08-04 09:47:08 +02005826 retval = (struct lys_node *)inout;
Radek Krejcie7770892017-01-24 13:18:01 +01005827 retval->module = module;
Michal Vaskoebeac942015-06-15 12:11:50 +02005828
Michal Vasko3e3228d2017-02-24 14:55:32 +01005829 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005830
Radek Krejcic189a952016-07-11 15:27:07 +02005831 /* insert the node into the schema tree */
5832 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5833 goto error;
5834 }
5835
Michal Vasko38d01f72015-06-15 09:41:06 +02005836 /* data statements */
5837 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie7770892017-01-24 13:18:01 +01005838 if (!sub->ns) {
5839 /* garbage */
5840 lyxml_free(module->ctx, sub);
5841 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01005842 /* extension */
5843 c_ext++;
5844 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005845 !strcmp(sub->name, "leaf-list") ||
5846 !strcmp(sub->name, "leaf") ||
5847 !strcmp(sub->name, "list") ||
5848 !strcmp(sub->name, "choice") ||
5849 !strcmp(sub->name, "uses") ||
5850 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005851 !strcmp(sub->name, "anyxml") ||
5852 !strcmp(sub->name, "anydata")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005853 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005854 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005855
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005856 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005857 } else if (!strcmp(sub->name, "typedef")) {
5858 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02005859
Radek Krejci1a31efe2016-07-29 11:04:16 +02005860 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005861 c_must++;
5862
Michal Vasko38d01f72015-06-15 09:41:06 +02005863 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005864 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005865 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005866 }
5867 }
5868
5869 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5870 if (c_tpdf) {
5871 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005872 if (!inout->tpdf) {
5873 LOGMEM;
5874 goto error;
5875 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005876 }
Radek Krejci19332802016-07-29 10:39:46 +02005877 if (c_must) {
5878 inout->must = calloc(c_must, sizeof *inout->must);
5879 if (!inout->must) {
5880 LOGMEM;
5881 goto error;
5882 }
5883 }
Radek Krejcie534c132016-11-23 13:32:31 +01005884 if (c_ext) {
5885 inout->ext = calloc(c_ext, sizeof *inout->ext);
5886 if (!inout->ext) {
5887 LOGMEM;
5888 goto error;
5889 }
5890 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005891
Radek Krejcie534c132016-11-23 13:32:31 +01005892 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5893 if (strcmp(sub->ns->value, LY_NSYIN)) {
5894 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005895 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 +01005896 retval->ext_size++;
5897 if (r) {
5898 goto error;
5899 }
5900 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005901 r = fill_yin_must(module, sub, &inout->must[inout->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02005902 inout->must_size++;
5903 if (r) {
5904 goto error;
5905 }
5906 } else { /* typedef */
5907 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
5908 inout->tpdf_size++;
5909 if (r) {
5910 goto error;
5911 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005912 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005913 }
5914
5915 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01005916 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko38d01f72015-06-15 09:41:06 +02005917 LY_TREE_FOR_SAFE(root.child, next, sub) {
5918 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005919 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005920 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005921 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005922 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005923 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005924 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005925 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005926 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005927 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005928 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005929 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005930 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005931 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005932 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005933 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005934 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005935 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005936 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005937 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005938 goto error;
5939 }
Radek Krejci73adb602015-07-02 18:07:40 +02005940
Michal Vasko345da0a2015-12-02 10:35:55 +01005941 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005942 }
5943
Michal Vasko508a50d2016-09-07 14:50:33 +02005944 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01005945 if (inout->must) {
5946 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005947 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005948 goto error;
5949 }
5950 } else {
5951 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5952 goto error;
5953 }
5954 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005955 }
5956
Michal Vasko38d01f72015-06-15 09:41:06 +02005957 return retval;
5958
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005959error:
Michal Vasko38d01f72015-06-15 09:41:06 +02005960
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005961 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02005962 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005963 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005964 }
5965
5966 return NULL;
5967}
5968
Michal Vasko0d343d12015-08-24 14:57:36 +02005969/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005970static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005971read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005972 int options, struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02005973{
Michal Vaskoc6551b32015-06-16 10:51:43 +02005974 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005975 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005976 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005977 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005978 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005979 int c_tpdf = 0, c_ftrs = 0, c_must = 0, c_ext = 0;
Radek Krejci478ef1d2017-01-24 13:56:09 +01005980 void *reallocated;
Michal Vasko0ea41032015-06-16 08:53:55 +02005981
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005982 if (parent && (module->version < 2)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005983 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "notification");
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005984 return NULL;
5985 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005986
Michal Vaskoc6551b32015-06-16 10:51:43 +02005987 memset(&root, 0, sizeof root);
5988
Michal Vasko0ea41032015-06-16 08:53:55 +02005989 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01005990 if (!notif) {
5991 LOGMEM;
5992 return NULL;
5993 }
Radek Krejci76512572015-08-04 09:47:08 +02005994 notif->nodetype = LYS_NOTIF;
5995 notif->prev = (struct lys_node *)notif;
5996 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005997
Radek Krejci07d0fb92017-01-13 14:11:05 +01005998 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005999 goto error;
6000 }
6001
Michal Vasko3e3228d2017-02-24 14:55:32 +01006002 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006003
Radek Krejcic189a952016-07-11 15:27:07 +02006004 /* insert the node into the schema tree */
6005 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6006 goto error;
6007 }
6008
Michal Vasko0ea41032015-06-16 08:53:55 +02006009 /* process rpc's specific children */
6010 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006011 if (strcmp(sub->ns->value, LY_NSYIN)) {
6012 /* extension */
6013 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006014 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02006015
Michal Vasko0ea41032015-06-16 08:53:55 +02006016 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01006017 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006018 !strcmp(sub->name, "leaf-list") ||
6019 !strcmp(sub->name, "leaf") ||
6020 !strcmp(sub->name, "list") ||
6021 !strcmp(sub->name, "choice") ||
6022 !strcmp(sub->name, "uses") ||
6023 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01006024 !strcmp(sub->name, "anyxml") ||
6025 !strcmp(sub->name, "anydata")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02006026 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006027 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02006028
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006029 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02006030 } else if (!strcmp(sub->name, "typedef")) {
6031 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006032 } else if (!strcmp(sub->name, "if-feature")) {
6033 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02006034 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02006035 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02006036 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006037 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02006038 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02006039 }
6040 }
6041
6042 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6043 if (c_tpdf) {
6044 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01006045 if (!notif->tpdf) {
6046 LOGMEM;
6047 goto error;
6048 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006049 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006050 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006051 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
6052 if (!notif->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01006053 LOGMEM;
6054 goto error;
6055 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006056 }
Radek Krejci19332802016-07-29 10:39:46 +02006057 if (c_must) {
6058 notif->must = calloc(c_must, sizeof *notif->must);
6059 if (!notif->must) {
Michal Vasko0ea41032015-06-16 08:53:55 +02006060 LOGMEM;
6061 goto error;
6062 }
6063 }
Radek Krejcie534c132016-11-23 13:32:31 +01006064 if (c_ext) {
Radek Krejci478ef1d2017-01-24 13:56:09 +01006065 /* some extensions may be already present from the substatements */
6066 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
6067 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01006068 LOGMEM;
6069 goto error;
6070 }
Radek Krejci478ef1d2017-01-24 13:56:09 +01006071 retval->ext = reallocated;
6072
6073 /* init memory */
6074 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006075 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006076
Radek Krejcie534c132016-11-23 13:32:31 +01006077 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6078 if (strcmp(sub->ns->value, LY_NSYIN)) {
6079 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006080 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 +01006081 retval->ext_size++;
6082 if (r) {
6083 goto error;
6084 }
6085 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006086 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
6087 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02006088 if (r) {
6089 goto error;
6090 }
Radek Krejci96299152016-06-22 10:17:50 +02006091 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006092 r = fill_yin_iffeature(retval, 0, sub, &notif->iffeature[notif->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006093 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006094 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006095 goto error;
6096 }
Radek Krejci19332802016-07-29 10:39:46 +02006097 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01006098 r = fill_yin_must(module, sub, &notif->must[notif->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02006099 notif->must_size++;
Radek Krejci0b24d752015-07-02 15:02:27 +02006100 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006101 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006102 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006103 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006104 }
6105
6106 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01006107 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko0ea41032015-06-16 08:53:55 +02006108 LY_TREE_FOR_SAFE(root.child, next, sub) {
6109 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006110 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006111 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006112 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006113 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006114 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006115 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006116 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006117 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006118 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006119 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006120 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006121 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006122 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006123 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006124 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02006125 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006126 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006127 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006128 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02006129 goto error;
6130 }
Radek Krejci73adb602015-07-02 18:07:40 +02006131
Michal Vasko345da0a2015-12-02 10:35:55 +01006132 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02006133 }
6134
Michal Vasko508a50d2016-09-07 14:50:33 +02006135 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01006136 if (notif->must) {
6137 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006138 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006139 goto error;
6140 }
6141 } else {
6142 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6143 goto error;
6144 }
6145 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006146 }
6147
Michal Vasko0ea41032015-06-16 08:53:55 +02006148 return retval;
6149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006150error:
Michal Vasko0ea41032015-06-16 08:53:55 +02006151
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006152 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02006153 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006154 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02006155 }
6156
6157 return NULL;
6158}
6159
Michal Vasko0d343d12015-08-24 14:57:36 +02006160/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02006161static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02006162read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01006163 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02006164{
Radek Krejcie0674f82015-06-15 13:58:51 +02006165 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006166 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02006167 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02006168 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006169 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01006170 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0, c_ext = 0;
Radek Krejci94596cf2017-01-24 13:19:16 +01006171 void *reallocated;
Michal Vasko38d01f72015-06-15 09:41:06 +02006172
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006173 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006174 if (module->version < 2) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006175 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "action");
Michal Vaskobb174852016-07-25 11:00:21 +02006176 return NULL;
6177 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006178 for (node = parent; node; node = lys_parent(node)) {
Radek Krejcia3b19f72016-09-30 13:02:45 +02006179 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006180 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006181 LOGVAL(LYE_INPAR, LY_VLOG_LYS, parent, strnodetype(node->nodetype), "action");
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006182 return NULL;
6183 }
6184 }
6185 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006186
Radek Krejcie0674f82015-06-15 13:58:51 +02006187 /* init */
6188 memset(&root, 0, sizeof root);
6189
Michal Vasko38d01f72015-06-15 09:41:06 +02006190 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01006191 if (!rpc) {
6192 LOGMEM;
6193 return NULL;
6194 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006195 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02006196 rpc->prev = (struct lys_node *)rpc;
6197 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006198
Radek Krejci07d0fb92017-01-13 14:11:05 +01006199 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006200 goto error;
6201 }
6202
Michal Vasko3e3228d2017-02-24 14:55:32 +01006203 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006204
Radek Krejcic189a952016-07-11 15:27:07 +02006205 /* insert the node into the schema tree */
6206 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6207 goto error;
6208 }
6209
Michal Vasko38d01f72015-06-15 09:41:06 +02006210 /* process rpc's specific children */
6211 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006212 if (strcmp(sub->ns->value, LY_NSYIN)) {
6213 /* extension */
6214 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006215 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006216 } else if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006217 if (c_input) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006218 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006219 goto error;
6220 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006221 c_input++;
Michal Vaskof3930de2015-10-22 12:03:59 +02006222 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006223 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006224 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006225 if (c_output) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006226 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006227 goto error;
6228 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006229 c_output++;
Michal Vaskof3930de2015-10-22 12:03:59 +02006230 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006231 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006232
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006233 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02006234 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02006235 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006236 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006237
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006238 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02006239 } else if (!strcmp(sub->name, "typedef")) {
6240 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006241 } else if (!strcmp(sub->name, "if-feature")) {
6242 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006243 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006244 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006245 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02006246 }
6247 }
6248
6249 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6250 if (c_tpdf) {
6251 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01006252 if (!rpc->tpdf) {
6253 LOGMEM;
6254 goto error;
6255 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006256 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006257 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006258 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
6259 if (!rpc->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01006260 LOGMEM;
6261 goto error;
6262 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006263 }
Radek Krejcie534c132016-11-23 13:32:31 +01006264 if (c_ext) {
Radek Krejci94596cf2017-01-24 13:19:16 +01006265 /* some extensions may be already present from the substatements */
6266 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
6267 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01006268 LOGMEM;
6269 goto error;
6270 }
Radek Krejci94596cf2017-01-24 13:19:16 +01006271 retval->ext = reallocated;
6272
6273 /* init memory */
6274 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006275 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006276
Radek Krejcie534c132016-11-23 13:32:31 +01006277 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6278 if (strcmp(sub->ns->value, LY_NSYIN)) {
6279 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006280 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 +01006281 retval->ext_size++;
6282 if (r) {
6283 goto error;
6284 }
6285 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006286 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
6287 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006288 if (r) {
6289 goto error;
6290 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006291 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006292 r = fill_yin_iffeature(retval, 0, sub, &rpc->iffeature[rpc->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006293 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006294 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006295 goto error;
6296 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006297 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006298 }
6299
6300 /* last part - process data nodes */
6301 LY_TREE_FOR_SAFE(root.child, next, sub) {
6302 if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006303 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006304 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006305 node = read_yin_input_output(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006306 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006307 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006308 goto error;
6309 }
Radek Krejci73adb602015-07-02 18:07:40 +02006310
Michal Vasko345da0a2015-12-02 10:35:55 +01006311 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006312 }
6313
Michal Vasko38d01f72015-06-15 09:41:06 +02006314 return retval;
6315
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006316error:
Michal Vasko38d01f72015-06-15 09:41:06 +02006317
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006318 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006319 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006320 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006321 }
6322
6323 return NULL;
6324}
6325
Michal Vasko0d343d12015-08-24 14:57:36 +02006326/* logs directly
6327 *
Radek Krejci74705112015-06-05 10:25:44 +02006328 * resolve - referenced grouping should be bounded to the namespace (resolved)
6329 * only when uses does not appear in grouping. In a case of grouping's uses,
6330 * we just get information but we do not apply augment or refine to it.
6331 */
Radek Krejci76512572015-08-04 09:47:08 +02006332static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01006333read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
6334 int options, struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02006335{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006336 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02006337 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006338 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006339 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01006340 int c_ref = 0, c_aug = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006341 int r;
Radek Krejcifdc0d702017-01-23 15:58:38 +01006342 void *reallocated;
Radek Krejci74705112015-06-05 10:25:44 +02006343
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006344 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01006345 if (!uses) {
6346 LOGMEM;
6347 return NULL;
6348 }
Radek Krejci76512572015-08-04 09:47:08 +02006349 uses->nodetype = LYS_USES;
6350 uses->prev = (struct lys_node *)uses;
6351 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02006352
Radek Krejcia9544502015-08-14 08:24:29 +02006353 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006354 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02006355
Radek Krejci07d0fb92017-01-13 14:11:05 +01006356 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006357 goto error;
6358 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006359
Michal Vasko3e3228d2017-02-24 14:55:32 +01006360 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006361
Radek Krejcic189a952016-07-11 15:27:07 +02006362 /* insert the node into the schema tree */
6363 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6364 goto error;
6365 }
6366
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006367 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02006368 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006369 if (strcmp(sub->ns->value, LY_NSYIN)) {
6370 /* extension */
6371 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006372 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006373 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006374 c_ref++;
6375 } else if (!strcmp(sub->name, "augment")) {
6376 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006377 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02006378 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006379 } else if (!strcmp(sub->name, "when")) {
6380 if (uses->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006381 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006382 goto error;
6383 }
6384
Radek Krejci5323b492017-01-16 15:40:11 +01006385 uses->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006386 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006387 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006388 goto error;
6389 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006390 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006391 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006392 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006393 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006394 }
6395 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006396
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006397 /* process properties with cardinality 0..n */
6398 if (c_ref) {
6399 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01006400 if (!uses->refine) {
6401 LOGMEM;
6402 goto error;
6403 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006404 }
6405 if (c_aug) {
6406 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01006407 if (!uses->augment) {
6408 LOGMEM;
6409 goto error;
6410 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006411 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006412 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006413 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
6414 if (!uses->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01006415 LOGMEM;
6416 goto error;
6417 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006418 }
Radek Krejcie534c132016-11-23 13:32:31 +01006419 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01006420 /* some extensions may be already present from the substatements */
6421 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
6422 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01006423 LOGMEM;
6424 goto error;
6425 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01006426 retval->ext = reallocated;
6427
6428 /* init memory */
6429 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006430 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006431
Radek Krejcie534c132016-11-23 13:32:31 +01006432 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6433 if (strcmp(sub->ns->value, LY_NSYIN)) {
6434 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006435 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 +01006436 retval->ext_size++;
6437 if (r) {
6438 goto error;
6439 }
6440 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02006441 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006442 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006443 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006444 goto error;
6445 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006446 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006447 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], options, unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006448 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006449 if (r) {
6450 goto error;
6451 }
6452 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006453 r = fill_yin_iffeature(retval, 0, sub, &uses->iffeature[uses->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006454 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006455 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006456 goto error;
6457 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006458 }
6459 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006460
Radek Krejci48464ed2016-03-17 15:44:09 +01006461 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006462 goto error;
6463 }
Radek Krejci74705112015-06-05 10:25:44 +02006464
Michal Vasko508a50d2016-09-07 14:50:33 +02006465 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01006466 if (uses->when) {
6467 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006468 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006469 goto error;
6470 }
6471 } else {
6472 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6473 goto error;
6474 }
6475 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006476 }
6477
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006478 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006479
6480error:
6481
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006482 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006484 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006485}
6486
Michal Vasko0d343d12015-08-24 14:57:36 +02006487/* logs directly
6488 *
6489 * common code for yin_read_module() and yin_read_submodule()
6490 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006491static int
Radek Krejcic071c542016-01-27 14:57:51 +01006492read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
6493 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02006494{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006495 struct ly_ctx *ctx = module->ctx;
Radek Krejci7417a082017-02-16 11:07:59 +01006496 struct lyxml_elem *next, *child, root, grps, augs, revs, exts;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006497 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006498 struct lys_module *trg;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006499 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01006500 int i, r, ret = -1;
Radek Krejcic071c542016-01-27 14:57:51 +01006501 int version_flag = 0;
Michal Vasko5de8a022017-02-08 10:57:26 +01006502 /* (sub)module substatements are ordered in groups, increment this value when moving to another group
6503 * 0 - header-stmts, 1 - linkage-stmts, 2 - meta-stmts, 3 - revision-stmts, 4 - body-stmts */
6504 int substmt_group;
6505 /* just remember last substatement for logging */
6506 const char *substmt_prev;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006507 /* counters */
Radek Krejcie534c132016-11-23 13:32:31 +01006508 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;
6509 int c_ext = 0, c_extinst = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01006510 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006511
Radek Krejcic071c542016-01-27 14:57:51 +01006512 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02006513 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01006514
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006515 /* init */
6516 memset(&root, 0, sizeof root);
6517 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006518 memset(&augs, 0, sizeof augs);
Radek Krejcie534c132016-11-23 13:32:31 +01006519 memset(&exts, 0, sizeof exts);
PavolVican9e81c6a2017-02-09 13:09:07 +01006520 memset(&revs, 0, sizeof revs);
Radek Krejcie0674f82015-06-15 13:58:51 +02006521
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006522 /*
6523 * in the first run, we process elements with cardinality of 1 or 0..1 and
6524 * count elements with cardinality 0..n. Data elements (choices, containers,
6525 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
6526 * need have all top-level and groupings already prepared at that time. In
6527 * the middle loop, we process other elements with carinality of 0..n since
6528 * we need to allocate arrays to store them.
6529 */
Michal Vasko5de8a022017-02-08 10:57:26 +01006530 substmt_group = 0;
6531 substmt_prev = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006532 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01006533 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02006534 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01006535 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006536 continue;
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006537 } else if (strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01006538 /* possible extension instance */
6539 lyxml_unlink_elem(module->ctx, child, 2);
6540 lyxml_add_child(module->ctx, &exts, child);
6541 c_extinst++;
6542 } else if (!submodule && !strcmp(child->name, "namespace")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006543 if (substmt_group > 0) {
6544 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6545 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6546 child->name, substmt_prev);
6547 goto error;
6548 }
6549
PavolVican9e81c6a2017-02-09 13:09:07 +01006550 if (trg->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006551 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006552 goto error;
6553 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006554 GETVAL(value, child, "uri");
PavolVican9e81c6a2017-02-09 13:09:07 +01006555 trg->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006556
Radek Krejci8d6b7422017-02-03 14:42:13 +01006557 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_NAMESPACE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006558 goto error;
6559 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006560 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006561
6562 substmt_prev = "namespace";
Radek Krejcic071c542016-01-27 14:57:51 +01006563 } else if (!submodule && !strcmp(child->name, "prefix")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006564 if (substmt_group > 0) {
6565 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6566 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6567 child->name, substmt_prev);
6568 goto error;
6569 }
6570
PavolVican9e81c6a2017-02-09 13:09:07 +01006571 if (trg->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006572 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006573 goto error;
6574 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006575 GETVAL(value, child, "value");
PavolVican9e81c6a2017-02-09 13:09:07 +01006576 if (lyp_check_identifier(value, LY_IDENT_PREFIX, trg, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006577 goto error;
6578 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006579 trg->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006580
Radek Krejci8d6b7422017-02-03 14:42:13 +01006581 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006582 goto error;
6583 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006584 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006585
6586 substmt_prev = "prefix";
Radek Krejcic071c542016-01-27 14:57:51 +01006587 } else if (submodule && !strcmp(child->name, "belongs-to")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006588 if (substmt_group > 0) {
6589 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6590 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6591 child->name, substmt_prev);
6592 goto error;
6593 }
6594
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006595 if (trg->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006596 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006597 goto error;
6598 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006599 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01006600 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006601 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006602 goto error;
6603 }
Radek Krejcif3886932015-06-04 17:36:06 +02006604
Radek Krejci8d6b7422017-02-03 14:42:13 +01006605 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_BELONGSTO, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006606 goto error;
6607 }
6608
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006609 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006610 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006611 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006612 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006613 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006614 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006615 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006616 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006617 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006618 goto error;
6619 }
6620 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006621 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006622 /* check here differs from a generic prefix check, since this prefix
6623 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02006624 */
Radek Krejci48464ed2016-03-17 15:44:09 +01006625 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006626 goto error;
6627 }
Radek Krejcic071c542016-01-27 14:57:51 +01006628 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02006629
Radek Krejci8d6b7422017-02-03 14:42:13 +01006630 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child->child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006631 goto error;
6632 }
6633
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006634 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01006635 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02006636
Michal Vasko5de8a022017-02-08 10:57:26 +01006637 substmt_prev = "belongs-to";
6638
Radek Krejcieb00f512015-07-01 16:44:58 +02006639 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006640 } else if (!strcmp(child->name, "import")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006641 if (substmt_group > 1) {
6642 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6643 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6644 child->name, substmt_prev);
6645 goto error;
6646 }
6647 substmt_group = 1;
6648
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006649 c_imp++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006650
6651 substmt_prev = "import";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006652 } else if (!strcmp(child->name, "revision")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006653 if (substmt_group > 3) {
6654 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6655 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6656 child->name, substmt_prev);
6657 goto error;
6658 }
6659 substmt_group = 3;
6660
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006661 c_rev++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006662
PavolVican9e81c6a2017-02-09 13:09:07 +01006663 lyxml_unlink_elem(ctx, child, 2);
6664 lyxml_add_child(ctx, &revs, child);
6665
Michal Vasko5de8a022017-02-08 10:57:26 +01006666 substmt_prev = "revision";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006667 } else if (!strcmp(child->name, "typedef")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006668 substmt_group = 4;
6669
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006670 c_tpdf++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006671
6672 substmt_prev = "typedef";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006673 } else if (!strcmp(child->name, "identity")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006674 substmt_group = 4;
6675
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006676 c_ident++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006677
6678 substmt_prev = "identity";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006679 } else if (!strcmp(child->name, "include")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006680 if (substmt_group > 1) {
6681 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6682 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6683 child->name, substmt_prev);
6684 goto error;
6685 }
6686 substmt_group = 1;
6687
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006688 c_inc++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006689
6690 substmt_prev = "include";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006691 } else if (!strcmp(child->name, "augment")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006692 substmt_group = 4;
6693
Radek Krejcif5be10f2015-06-16 13:29:36 +02006694 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006695 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01006696 lyxml_unlink_elem(ctx, child, 2);
6697 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006698
Michal Vasko5de8a022017-02-08 10:57:26 +01006699 substmt_prev = "augment";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006700 } else if (!strcmp(child->name, "feature")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006701 substmt_group = 4;
6702
Radek Krejci3cf9e222015-06-18 11:37:50 +02006703 c_ftrs++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006704
Michal Vasko5de8a022017-02-08 10:57:26 +01006705 substmt_prev = "feature";
Michal Vasko5de8a022017-02-08 10:57:26 +01006706
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006707 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006708 } else if (!strcmp(child->name, "container") ||
6709 !strcmp(child->name, "leaf-list") ||
6710 !strcmp(child->name, "leaf") ||
6711 !strcmp(child->name, "list") ||
6712 !strcmp(child->name, "choice") ||
6713 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006714 !strcmp(child->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01006715 !strcmp(child->name, "anydata") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006716 !strcmp(child->name, "rpc") ||
6717 !strcmp(child->name, "notification")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006718 substmt_group = 4;
6719
Radek Krejcic071c542016-01-27 14:57:51 +01006720 lyxml_unlink_elem(ctx, child, 2);
6721 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006722
Michal Vasko5de8a022017-02-08 10:57:26 +01006723 substmt_prev = "data definition";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006724 } else if (!strcmp(child->name, "grouping")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006725 substmt_group = 4;
6726
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006727 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01006728 lyxml_unlink_elem(ctx, child, 2);
6729 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006730
Michal Vasko5de8a022017-02-08 10:57:26 +01006731 substmt_prev = "grouping";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006732 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006733 } else if (!strcmp(child->name, "description")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006734 if (substmt_group > 2) {
6735 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6736 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6737 child->name, substmt_prev);
6738 goto error;
6739 }
6740 substmt_group = 2;
6741
Radek Krejcic071c542016-01-27 14:57:51 +01006742 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006743 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006744 goto error;
6745 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006746 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006747 goto error;
6748 }
Radek Krejcic071c542016-01-27 14:57:51 +01006749 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006750 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006751 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006752 goto error;
6753 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006754
6755 substmt_prev = "description";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006756 } else if (!strcmp(child->name, "reference")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006757 if (substmt_group > 2) {
6758 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6759 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6760 child->name, substmt_prev);
6761 goto error;
6762 }
6763 substmt_group = 2;
6764
Radek Krejcic071c542016-01-27 14:57:51 +01006765 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006766 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006767 goto error;
6768 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006769 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006770 goto error;
6771 }
Radek Krejcic071c542016-01-27 14:57:51 +01006772 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006773 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006774 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006775 goto error;
6776 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006777
6778 substmt_prev = "reference";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006779 } else if (!strcmp(child->name, "organization")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006780 if (substmt_group > 2) {
6781 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6782 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6783 child->name, substmt_prev);
6784 goto error;
6785 }
6786 substmt_group = 2;
6787
Radek Krejcic071c542016-01-27 14:57:51 +01006788 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006789 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006790 goto error;
6791 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006792 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_ORGANIZATION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006793 goto error;
6794 }
Radek Krejcic071c542016-01-27 14:57:51 +01006795 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006796 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006797 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006798 goto error;
6799 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006800
6801 substmt_prev = "organization";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006802 } else if (!strcmp(child->name, "contact")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006803 if (substmt_group > 2) {
6804 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6805 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6806 child->name, substmt_prev);
6807 goto error;
6808 }
6809 substmt_group = 2;
6810
Radek Krejcic071c542016-01-27 14:57:51 +01006811 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006812 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006813 goto error;
6814 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006815 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_CONTACT, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006816 goto error;
6817 }
Radek Krejcic071c542016-01-27 14:57:51 +01006818 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006819 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006820 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006821 goto error;
6822 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006823
6824 substmt_prev = "contact";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006825 } else if (!strcmp(child->name, "yang-version")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006826 if (substmt_group > 0) {
6827 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6828 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6829 child->name, substmt_prev);
6830 goto error;
6831 }
6832
Radek Krejcic071c542016-01-27 14:57:51 +01006833 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006834 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006835 goto error;
6836 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006837 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02006838 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006839 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006840 goto error;
6841 }
Radek Krejcic071c542016-01-27 14:57:51 +01006842 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006843 if (!strcmp(value, "1")) {
6844 if (submodule) {
6845 if (module->version > 1) {
6846 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6847 goto error;
6848 }
6849 } else {
6850 module->version = 1;
6851 }
6852 } else {
6853 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006854 if (module->version < 2) {
Michal Vasko88de3e42016-06-29 11:05:32 +02006855 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6856 goto error;
6857 }
6858 } else {
6859 module->version = 2;
6860 }
6861 }
6862
Radek Krejci8d6b7422017-02-03 14:42:13 +01006863 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_VERSION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006864 goto error;
6865 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006866 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006867
Michal Vasko5de8a022017-02-08 10:57:26 +01006868 substmt_prev = "yang-version";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006869 } else if (!strcmp(child->name, "extension")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006870 substmt_group = 4;
6871
Radek Krejcia1a6b762016-11-14 09:53:38 +09006872 c_ext++;
Radek Krejci5166a892015-07-02 16:44:24 +02006873
Michal Vasko5de8a022017-02-08 10:57:26 +01006874 substmt_prev = "extension";
Radek Krejcia1a6b762016-11-14 09:53:38 +09006875 } else if (!strcmp(child->name, "deviation")) {
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006876 substmt_group = 4;
6877
Radek Krejcia1a6b762016-11-14 09:53:38 +09006878 c_dev++;
6879
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006880 substmt_prev = "deviation";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006881 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01006882 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006883 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006884 }
6885 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006886
Radek Krejcic071c542016-01-27 14:57:51 +01006887 /* check for mandatory statements */
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006888 if (submodule) {
6889 if (!submodule->prefix) {
6890 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
6891 goto error;
6892 }
6893 if (!version_flag) {
6894 /* check version compatibility with the main module */
6895 if (module->version > 1) {
6896 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6897 goto error;
6898 }
6899 }
6900 } else {
PavolVican9e81c6a2017-02-09 13:09:07 +01006901 if (!trg->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006902 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006903 goto error;
6904 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006905 if (!trg->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006906 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006907 goto error;
6908 }
6909 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02006910
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006911 /* allocate arrays for elements with cardinality of 0..n */
6912 if (c_imp) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006913 trg->imp = calloc(c_imp, sizeof *trg->imp);
Radek Krejcic071c542016-01-27 14:57:51 +01006914 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01006915 LOGMEM;
6916 goto error;
6917 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006918 }
6919 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006920 trg->rev = calloc(c_rev, sizeof *trg->rev);
6921 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01006922 LOGMEM;
6923 goto error;
6924 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006925 }
6926 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01006927 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
6928 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01006929 LOGMEM;
6930 goto error;
6931 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006932 }
6933 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01006934 trg->ident = calloc(c_ident, sizeof *trg->ident);
6935 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01006936 LOGMEM;
6937 goto error;
6938 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006939 }
6940 if (c_inc) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006941 trg->inc = calloc(c_inc, sizeof *trg->inc);
Radek Krejcic071c542016-01-27 14:57:51 +01006942 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01006943 LOGMEM;
6944 goto error;
6945 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006946 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006947 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01006948 trg->augment = calloc(c_aug, sizeof *trg->augment);
6949 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01006950 LOGMEM;
6951 goto error;
6952 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006953 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006954 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01006955 trg->features = calloc(c_ftrs, sizeof *trg->features);
6956 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01006957 LOGMEM;
6958 goto error;
6959 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006960 }
Radek Krejcieb00f512015-07-01 16:44:58 +02006961 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006962 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
6963 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01006964 LOGMEM;
6965 goto error;
6966 }
Radek Krejcieb00f512015-07-01 16:44:58 +02006967 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09006968 if (c_ext) {
6969 trg->extensions = calloc(c_ext, sizeof *trg->extensions);
6970 if (!trg->extensions) {
6971 LOGMEM;
6972 goto error;
6973 }
6974 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006975
PavolVican9e81c6a2017-02-09 13:09:07 +01006976 /* middle part 1 - process revision and then check whether this (sub)module was not already parsed, add it there */
6977 LY_TREE_FOR_SAFE(revs.child, next, child) {
Radek Krejci7417a082017-02-16 11:07:59 +01006978 r = fill_yin_revision(trg, child, &trg->rev[trg->rev_size], unres);
6979 trg->rev_size++;
6980 if (r) {
PavolVican9e81c6a2017-02-09 13:09:07 +01006981 goto error;
6982 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006983
Radek Krejci7417a082017-02-16 11:07:59 +01006984 /* check uniqueness of the revision date - not required by RFC */
6985 for (i = 0; i < (trg->rev_size - 1); i++) {
6986 if (!strcmp(trg->rev[i].date, trg->rev[trg->rev_size - 1].date)) {
6987 LOGWRN("Module's revisions are not unique (%s).", trg->rev[trg->rev_size - 1].date);
6988 break;
PavolVican9e81c6a2017-02-09 13:09:07 +01006989 }
6990 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006991
6992 lyxml_free(ctx, child);
6993 }
6994
6995 /* check the module with respect to the context now */
6996 if (!submodule) {
6997 switch (lyp_ctx_check_module(module)) {
6998 case -1:
6999 goto error;
7000 case 0:
7001 break;
7002 case 1:
7003 /* it's already there */
7004 ret = 1;
7005 goto error;
7006 }
7007 }
7008
7009 /* middle part 2 - process nodes with cardinality of 0..n except the data nodes and augments */
Michal Vasko2f7925f2015-10-21 15:06:56 +02007010 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02007011 if (!strcmp(child->name, "import")) {
Radek Krejcie534c132016-11-23 13:32:31 +01007012 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size], unres);
Radek Krejcic071c542016-01-27 14:57:51 +01007013 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007014 if (r) {
7015 goto error;
7016 }
Radek Krejcice7fb782015-05-29 16:52:34 +02007017
Radek Krejci1d82ef62015-08-07 14:44:40 +02007018 } else if (!strcmp(child->name, "include")) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007019 r = fill_yin_include(module, submodule, child, &trg->inc[trg->inc_size], unres);
7020 trg->inc_size++;
7021 if (r) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007022 goto error;
7023 }
Radek Krejcice7fb782015-05-29 16:52:34 +02007024
Radek Krejci1d82ef62015-08-07 14:44:40 +02007025 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007026 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
7027 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007028 if (r) {
7029 goto error;
7030 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007031
Radek Krejci1d82ef62015-08-07 14:44:40 +02007032 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007033 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
7034 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007035 if (r) {
7036 goto error;
7037 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007038
Radek Krejci1d82ef62015-08-07 14:44:40 +02007039 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007040 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
7041 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02007042 if (r) {
7043 goto error;
7044 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007045
Radek Krejcia1a6b762016-11-14 09:53:38 +09007046 } else if (!strcmp(child->name, "extension")) {
Radek Krejcie534c132016-11-23 13:32:31 +01007047 r = fill_yin_extension(trg, child, &trg->extensions[trg->extensions_size], unres);
Radek Krejcia1a6b762016-11-14 09:53:38 +09007048 trg->extensions_size++;
7049 if (r) {
7050 goto error;
7051 }
7052
Radek Krejci1d82ef62015-08-07 14:44:40 +02007053 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01007054 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
7055 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02007056 if (r) {
7057 goto error;
7058 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007059 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007060 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02007061
Radek Krejcie534c132016-11-23 13:32:31 +01007062 /* process extension instances */
Radek Krejci8ee94802017-02-10 12:38:40 +01007063 if (c_extinst) {
7064 /* some extensions may be already present from the substatements */
7065 reallocated = realloc(trg->ext, (c_extinst + trg->ext_size) * sizeof *trg->ext);
7066 if (!reallocated) {
7067 LOGMEM;
Radek Krejcie534c132016-11-23 13:32:31 +01007068 goto error;
7069 }
Radek Krejci8ee94802017-02-10 12:38:40 +01007070 trg->ext = reallocated;
7071
7072 /* init memory */
7073 memset(&trg->ext[trg->ext_size], 0, c_extinst * sizeof *trg->ext);
7074
7075 LY_TREE_FOR_SAFE(exts.child, next, child) {
7076 r = lyp_yin_fill_ext(trg, LYEXT_PAR_MODULE, 0, 0, trg, child, &trg->ext, trg->ext_size, unres);
7077 trg->ext_size++;
7078 if (r) {
7079 goto error;
7080 }
7081 }
Radek Krejcie534c132016-11-23 13:32:31 +01007082 }
7083
Radek Krejcif5be10f2015-06-16 13:29:36 +02007084 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01007085 * refer to them. Submodule's data nodes are stored in the
7086 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007087 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02007088 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007089 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007090 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007091 goto error;
7092 }
Radek Krejci74705112015-06-05 10:25:44 +02007093
Michal Vasko345da0a2015-12-02 10:35:55 +01007094 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007095 }
Radek Krejci74705112015-06-05 10:25:44 +02007096
Radek Krejcif5be10f2015-06-16 13:29:36 +02007097 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02007098 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02007099
Radek Krejci1d82ef62015-08-07 14:44:40 +02007100 if (!strcmp(child->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007101 node = read_yin_container(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007102 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007103 node = read_yin_leaflist(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007104 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007105 node = read_yin_leaf(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007106 } else if (!strcmp(child->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007107 node = read_yin_list(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007108 } else if (!strcmp(child->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007109 node = read_yin_choice(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007110 } else if (!strcmp(child->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007111 node = read_yin_uses(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007112 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007113 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02007114 } else if (!strcmp(child->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007115 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007116 } else if (!strcmp(child->name, "rpc")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007117 node = read_yin_rpc_action(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007118 } else if (!strcmp(child->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007119 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007120 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02007121 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007122 goto error;
7123 }
Radek Krejci25d782a2015-05-22 15:03:23 +02007124
Michal Vasko345da0a2015-12-02 10:35:55 +01007125 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007126 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007127
Michal Vasko2f7925f2015-10-21 15:06:56 +02007128 /* ... and finally augments (last, so we can augment our data, for instance) */
7129 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007130 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], 0, unres);
Radek Krejcic071c542016-01-27 14:57:51 +01007131 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02007132
Michal Vasko2f7925f2015-10-21 15:06:56 +02007133 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02007134 goto error;
7135 }
Michal Vasko345da0a2015-12-02 10:35:55 +01007136 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02007137 }
7138
PavolVican9e81c6a2017-02-09 13:09:07 +01007139 return 0;
Radek Krejciefaeba32015-05-27 14:30:57 +02007140
7141error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007142 while (root.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007143 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007144 }
7145 while (grps.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007146 lyxml_free(ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007147 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007148 while (augs.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007149 lyxml_free(ctx, augs.child);
7150 }
7151 while (revs.child) {
7152 lyxml_free(ctx, revs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02007153 }
Radek Krejcie534c132016-11-23 13:32:31 +01007154 while (exts.child) {
7155 lyxml_free(module->ctx, exts.child);
7156 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007157
PavolVican9e81c6a2017-02-09 13:09:07 +01007158 return ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007159}
7160
Michal Vasko0d343d12015-08-24 14:57:36 +02007161/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007162struct lys_submodule *
7163yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02007164{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007165 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01007166 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007167 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02007168
Michal Vasko5a721fd2016-02-16 12:16:48 +01007169 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02007170
Radek Krejcie1bacd72017-03-01 13:18:46 +01007171 yin = lyxml_parse_mem(module->ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007172 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01007173 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007174 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007175
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007176 /* check root element */
7177 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01007178 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007179 goto error;
7180 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007181
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007182 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01007183 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007184 goto error;
7185 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007186
Michal Vasko5a721fd2016-02-16 12:16:48 +01007187 submodule = calloc(1, sizeof *submodule);
7188 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007189 LOGMEM;
7190 goto error;
7191 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007192
Michal Vasko5a721fd2016-02-16 12:16:48 +01007193 submodule->ctx = module->ctx;
7194 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
7195 submodule->type = 1;
7196 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02007197
Radek Krejci9e757e02017-03-08 17:18:09 +01007198 /* add into the list of processed modules */
7199 if (lyp_check_circmod_add((struct lys_module *)submodule)) {
7200 goto error;
7201 }
7202
Michal Vasko5a721fd2016-02-16 12:16:48 +01007203 LOGVRB("Reading submodule \"%s\".", submodule->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007204 /* module cannot be changed in this case and 1 cannot be returned */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007205 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007206 goto error;
7207 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007208
Radek Krejci33fc4772017-01-26 16:00:35 +01007209 lyp_sort_revisions((struct lys_module *)submodule);
7210
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007211 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01007212 lyxml_free(module->ctx, yin);
Radek Krejci9e757e02017-03-08 17:18:09 +01007213 lyp_check_circmod_pop(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02007214
Michal Vasko5a721fd2016-02-16 12:16:48 +01007215 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007216 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02007217
7218error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007219 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007220 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01007221 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01007222
Michal Vasko5a721fd2016-02-16 12:16:48 +01007223 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01007224 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01007225 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01007226 }
7227
Michal Vasko5a721fd2016-02-16 12:16:48 +01007228 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01007229
Radek Krejci9e757e02017-03-08 17:18:09 +01007230 lyp_check_circmod_pop(module->ctx);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007231 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
7232 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007233 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007234 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02007235}
7236
Michal Vasko0d343d12015-08-24 14:57:36 +02007237/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02007238struct lys_module *
Radek Krejci37f9ba32017-02-10 16:50:35 +01007239yin_read_module_(struct ly_ctx *ctx, struct lyxml_elem *yin, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02007240{
Pavol Vicanc99b59e2016-03-22 15:46:39 +01007241 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01007242 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007243 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01007244 int ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007245
Radek Krejcic071c542016-01-27 14:57:51 +01007246 unres = calloc(1, sizeof *unres);
7247 if (!unres) {
7248 LOGMEM;
7249 return NULL;
7250 }
7251
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007252 /* check root element */
7253 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci9a909bd2016-10-24 15:45:51 +02007254 if (ly_strequal("submodule", yin->name, 0)) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007255 LOGVAL(LYE_SUBMODULE, LY_VLOG_NONE, NULL);
7256 } else {
7257 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci9a909bd2016-10-24 15:45:51 +02007258 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007259 goto error;
7260 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007261
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007262 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01007263 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007264 goto error;
7265 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007266
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007267 module = calloc(1, sizeof *module);
7268 if (!module) {
7269 LOGMEM;
7270 goto error;
7271 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007272
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007273 module->ctx = ctx;
7274 module->name = lydict_insert(ctx, value, strlen(value));
7275 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02007276 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02007277
Radek Krejci9e757e02017-03-08 17:18:09 +01007278 /* add into the list of processed modules */
7279 if (lyp_check_circmod_add(module)) {
7280 goto error;
7281 }
7282
Michal Vasko9f258e42016-02-11 11:36:27 +01007283 LOGVRB("Reading module \"%s\".", module->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007284 ret = read_sub_module(module, NULL, yin, unres);
7285 if (ret == -1) {
Radek Krejcic071c542016-01-27 14:57:51 +01007286 goto error;
7287 }
7288
PavolVican9e81c6a2017-02-09 13:09:07 +01007289 if (ret == 1) {
7290 assert(!unres->count);
7291 } else {
7292 /* resolve rest of unres items */
7293 if (unres->count && resolve_unres_schema(module, unres)) {
7294 goto error;
7295 }
7296
7297 /* check correctness of includes */
7298 if (lyp_check_include_missing(module)) {
7299 goto error;
7300 }
Michal Vasko7b460e52017-02-10 14:50:26 +01007301
7302 /* remove our submodules from the parsed submodules list */
7303 lyp_del_includedup(module);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007304 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007305
Radek Krejci95f22ae2017-01-20 14:25:53 +01007306 lyp_sort_revisions(module);
Radek Krejci6bd2c022017-02-01 15:04:49 +01007307
7308 if (lyp_rfn_apply_ext(module) || lyp_deviation_apply_ext(module)) {
7309 goto error;
7310 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01007311
Radek Krejciff4874d2016-03-07 12:30:50 +01007312 if (revision) {
7313 /* check revision of the parsed model */
7314 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01007315 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
7316 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01007317 goto error;
7318 }
7319 }
7320
PavolVican9e81c6a2017-02-09 13:09:07 +01007321 /* add into context if not already there */
7322 if (!ret) {
7323 if (module->deviation_size && !module->implemented) {
7324 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
7325 /* deviations always causes target to be made implemented,
7326 * but augents and leafrefs not, so we have to apply them now */
7327 if (lys_set_implemented(module)) {
7328 goto error;
7329 }
7330 }
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007331
PavolVican9e81c6a2017-02-09 13:09:07 +01007332 if (lyp_ctx_add_module(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02007333 goto error;
7334 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007335 } else {
7336 /* free what was parsed */
7337 lys_free(module, NULL, 0);
7338
7339 /* get the model from the context */
7340 module = (struct lys_module *)ly_ctx_get_module(ctx, value, revision);
7341 assert(module);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007342 }
7343
Radek Krejcic071c542016-01-27 14:57:51 +01007344 unres_schema_free(NULL, &unres);
Radek Krejci9e757e02017-03-08 17:18:09 +01007345 lyp_check_circmod_pop(ctx);
Michal Vasko9f258e42016-02-11 11:36:27 +01007346 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007347 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007348
7349error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007350 /* cleanup */
Radek Krejcib8c07b82016-02-12 11:11:55 +01007351 unres_schema_free(module, &unres);
7352
7353 if (!module) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007354 if (ly_vecode != LYVE_SUBMODULE) {
7355 LOGERR(ly_errno, "Module parsing failed.");
7356 }
Radek Krejcib8c07b82016-02-12 11:11:55 +01007357 return NULL;
7358 }
7359
7360 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02007361
Radek Krejci9e757e02017-03-08 17:18:09 +01007362 lyp_check_circmod_pop(ctx);
Michal Vaskocf0489e2017-02-13 11:57:45 +01007363 lyp_del_includedup(module);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007364 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01007365 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007366 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007367}
Radek Krejci8d6b7422017-02-03 14:42:13 +01007368
Radek Krejci37f9ba32017-02-10 16:50:35 +01007369/* logs directly */
7370struct lys_module *
7371yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
7372{
7373 struct lyxml_elem *yin;
7374 struct lys_module *result;
7375
Radek Krejcie1bacd72017-03-01 13:18:46 +01007376 yin = lyxml_parse_mem(ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci37f9ba32017-02-10 16:50:35 +01007377 if (!yin) {
7378 LOGERR(ly_errno, "Module parsing failed.");
7379 return NULL;
7380 }
7381
7382 result = yin_read_module_(ctx, yin, revision, implement);
7383
7384 lyxml_free(ctx, yin);
7385
7386 return result;
7387}
7388
Radek Krejcic1885952017-02-07 09:37:51 +01007389static int
7390yin_parse_extcomplex_bool(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007391 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007392 const char *true_val, const char *false_val, struct unres_schema *unres)
7393{
7394 uint8_t *val;
7395 const char *str;
7396 struct lyext_substmt *info;
7397
7398 val = lys_ext_complex_get_substmt(stmt, ext, &info);
7399 if (!val) {
7400 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7401 return EXIT_FAILURE;
7402 }
7403 if (*val) {
7404 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7405 return EXIT_FAILURE;
7406 }
7407
Radek Krejcidb35f172017-02-27 11:03:01 +01007408 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007409 return EXIT_FAILURE;
7410 }
7411
7412 str = lyxml_get_attr(node, "value", NULL);
7413 if (!str) {
7414 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
7415 } else if (true_val && !strcmp(true_val, str)) {
7416 /* true value */
7417 *val = 1;
7418 } else if (false_val && !strcmp(false_val, str)) {
7419 /* false value */
7420 *val = 2;
7421 } else {
7422 /* unknown value */
7423 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
7424 return EXIT_FAILURE;
7425 }
7426
7427 return EXIT_SUCCESS;
7428}
7429
Radek Krejci8d6b7422017-02-03 14:42:13 +01007430/*
7431 * argelem - 1 if the value is stored in a standalone YIN element, 0 if stored as attribute
7432 * argname - name of the element/attribute where the value is stored
7433 */
7434static int
7435yin_parse_extcomplex_str(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007436 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejci8d6b7422017-02-03 14:42:13 +01007437 int argelem, const char *argname, struct unres_schema *unres)
7438{
7439 int c;
PavolVican99c70722017-02-18 17:25:52 +01007440 const char **str, ***p = NULL, *value;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007441 void *reallocated;
7442 struct lyext_substmt *info;
7443
7444 str = lys_ext_complex_get_substmt(stmt, ext, &info);
7445 if (!str) {
7446 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7447 return EXIT_FAILURE;
7448 }
7449 if (info->cardinality < LY_STMT_CARD_SOME && *str) {
7450 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7451 return EXIT_FAILURE;
7452 }
7453
7454 c = 0;
7455 if (info->cardinality >= LY_STMT_CARD_SOME) {
7456 /* there can be multiple instances, str is actually const char *** */
7457 p = (const char ***)str;
Radek Krejci56c80412017-02-09 10:44:16 +01007458 if (!p[0]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007459 /* allocate initial array */
Radek Krejci56c80412017-02-09 10:44:16 +01007460 p[0] = malloc(2 * sizeof(const char *));
7461 if (stmt == LY_STMT_BELONGSTO) {
7462 /* allocate another array for the belongs-to's prefixes */
7463 p[1] = malloc(2 * sizeof(const char *));
PavolVican99c70722017-02-18 17:25:52 +01007464 } else if (stmt == LY_STMT_ARGUMENT) {
7465 /* allocate another array for the yin element */
PavolVican4b80d042017-02-23 14:30:27 +01007466 ((uint8_t **)p)[1] = malloc(2 * sizeof(uint8_t));
Radek Krejci56c80412017-02-09 10:44:16 +01007467 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007468 } else {
Radek Krejci56c80412017-02-09 10:44:16 +01007469 /* get the index in the array to add new item */
7470 for (c = 0; p[0][c]; c++);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007471 }
Radek Krejci56c80412017-02-09 10:44:16 +01007472 str = p[0];
Radek Krejci8d6b7422017-02-03 14:42:13 +01007473 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007474 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, c, unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007475 return EXIT_FAILURE;
7476 }
7477
7478 if (argelem) {
Radek Krejci56c80412017-02-09 10:44:16 +01007479 str[c] = read_yin_subnode(mod->ctx, node, argname);
7480 if (!str[c]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007481 return EXIT_FAILURE;
7482 }
Radek Krejci56c80412017-02-09 10:44:16 +01007483 } else {
7484 str[c] = lyxml_get_attr(node, argname, NULL);
7485 if (!str[c]) {
7486 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, argname, node->name);
7487 return EXIT_FAILURE;
7488 } else {
7489 str[c] = lydict_insert(mod->ctx, str[c], 0);
7490 }
7491
7492 if (stmt == LY_STMT_BELONGSTO) {
7493 /* get the belongs-to's mandatory prefix substatement */
7494 if (!node->child) {
7495 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", node->name);
7496 return EXIT_FAILURE;
7497 } else if (strcmp(node->child->name, "prefix")) {
7498 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
7499 return EXIT_FAILURE;
7500 } else if (node->child->next) {
7501 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
7502 return EXIT_FAILURE;
7503 }
7504 /* and now finally get the value */
7505 if (p) {
7506 str = p[1];
7507 } else {
7508 str++;
7509 }
7510 str[c] = lyxml_get_attr(node->child, "value", ((void *)0));
7511 if (!str[c]) {
7512 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
7513 return EXIT_FAILURE;
7514 }
7515 str[c] = lydict_insert(mod->ctx, str[c], 0);
7516
PavolVican6d400872017-03-01 15:19:18 +01007517 if (!str[c] || lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node->child, LYEXT_SUBSTMT_PREFIX, c, unres)) {
Radek Krejci56c80412017-02-09 10:44:16 +01007518 return EXIT_FAILURE;
7519 }
PavolVican99c70722017-02-18 17:25:52 +01007520 } else if (stmt == LY_STMT_ARGUMENT) {
7521 str = (p) ? p[1] : str + 1;
7522 if (!node->child) {
7523 /* default value of yin element */
7524 ((uint8_t *)str)[c] = 2;
7525 } else {
7526 /* get optional yin-element substatement */
7527 if (strcmp(node->child->name, "yin-element")) {
7528 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
7529 return EXIT_FAILURE;
7530 } else if (node->child->next) {
7531 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
7532 return EXIT_FAILURE;
7533 } else {
7534 /* and now finally get the value */
7535 value = lyxml_get_attr(node->child, "value", NULL);
7536 if (!value) {
7537 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
7538 return EXIT_FAILURE;
7539 }
7540 if (ly_strequal(value, "true", 0)) {
7541 ((uint8_t *)str)[c] = 1;
7542 } else if (ly_strequal(value, "false", 0)) {
7543 ((uint8_t *)str)[c] = 2;
7544 } else {
7545 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
7546 return EXIT_FAILURE;
7547 }
7548
7549 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node->child, LYEXT_SUBSTMT_YINELEM, c, unres)) {
7550 return EXIT_FAILURE;
7551 }
7552 }
7553 }
Radek Krejci56c80412017-02-09 10:44:16 +01007554 }
7555 }
7556 if (p) {
7557 /* enlarge the array(s) */
7558 reallocated = realloc(p[0], (c + 2) * sizeof(const char *));
7559 if (!reallocated) {
7560 LOGMEM;
7561 lydict_remove(mod->ctx, p[0][c]);
7562 p[0][c] = NULL;
7563 return EXIT_FAILURE;
7564 }
7565 p[0] = reallocated;
7566 p[0][c + 1] = NULL;
7567
7568 if (stmt == LY_STMT_BELONGSTO) {
7569 /* enlarge the second belongs-to's array with prefixes */
7570 reallocated = realloc(p[1], (c + 2) * sizeof(const char *));
7571 if (!reallocated) {
7572 LOGMEM;
7573 lydict_remove(mod->ctx, p[1][c]);
7574 p[1][c] = NULL;
7575 return EXIT_FAILURE;
7576 }
7577 p[1] = reallocated;
7578 p[1][c + 1] = NULL;
PavolVican99c70722017-02-18 17:25:52 +01007579 } else if (stmt == LY_STMT_ARGUMENT){
7580 /* enlarge the second argument's array with yin element */
7581 reallocated = realloc(p[1], (c + 2) * sizeof(uint8_t));
7582 if (!reallocated) {
7583 LOGMEM;
7584 ((uint8_t *)p[1])[c] = 0;
7585 return EXIT_FAILURE;
7586 }
7587 p[1] = reallocated;
7588 ((uint8_t *)p[1])[c + 1] = 0;
Radek Krejci56c80412017-02-09 10:44:16 +01007589 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007590 }
7591
7592 return EXIT_SUCCESS;
7593}
7594
7595static void *
7596yin_getplace_for_extcomplex_flags(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt,
7597 uint16_t mask)
7598{
7599 void *data;
7600 struct lyext_substmt *info;
7601
7602 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7603 if (!data) {
7604 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7605 return NULL;
7606 }
7607 if (info->cardinality < LY_STMT_CARD_SOME && ((*(uint16_t *)data) & mask)) {
7608 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7609 return NULL;
7610 }
7611
7612 return data;
7613}
7614
Radek Krejcic1885952017-02-07 09:37:51 +01007615static int
7616yin_parse_extcomplex_flag(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007617 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007618 const char *val1_str, const char *val2_str, uint16_t mask,
7619 uint16_t val1, uint16_t val2, struct unres_schema *unres)
7620{
7621 uint16_t *val;
7622 const char *str;
7623
7624 val = yin_getplace_for_extcomplex_flags(node, ext, stmt, mask);
7625 if (!val) {
7626 return EXIT_FAILURE;
7627 }
7628
7629 str = lyxml_get_attr(node, "value", NULL);
7630 if (!str) {
7631 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
7632 } else if (!strcmp(val1_str, str)) {
7633 *val = *val | val1;
7634 } else if (!strcmp(val2_str, str)) {
7635 *val = *val | val2;
7636 } else {
7637 /* unknown value */
7638 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
7639 return EXIT_FAILURE;
7640 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007641 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007642 return EXIT_FAILURE;
7643 }
7644 return EXIT_SUCCESS;
7645}
7646
Radek Krejcif95b6292017-02-13 15:57:37 +01007647static struct lys_node **
7648yin_getplace_for_extcomplex_node(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7649{
7650 struct lyext_substmt *info;
7651 struct lys_node **snode, *siter;
7652
7653 snode = lys_ext_complex_get_substmt(stmt, ext, &info);
7654 if (!snode) {
7655 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7656 return NULL;
7657 }
7658 if (info->cardinality < LY_STMT_CARD_SOME) {
7659 LY_TREE_FOR(*snode, siter) {
7660 if (stmt == lys_snode2stmt(siter->nodetype)) {
7661 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7662 return NULL;
7663 }
7664 }
7665 }
7666
7667 return snode;
7668}
7669
Radek Krejci8d6b7422017-02-03 14:42:13 +01007670static void **
7671yin_getplace_for_extcomplex_struct(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7672{
7673 int c;
7674 void **data, ***p = NULL;
7675 void *reallocated;
7676 struct lyext_substmt *info;
7677
7678 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7679 if (!data) {
7680 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7681 return NULL;
7682 }
7683 if (info->cardinality < LY_STMT_CARD_SOME && *data) {
7684 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7685 return NULL;
7686 }
7687
7688 c = 0;
7689 if (info->cardinality >= LY_STMT_CARD_SOME) {
7690 /* there can be multiple instances, so instead of pointer to array,
7691 * we have in data pointer to pointer to array */
7692 p = (void ***)data;
7693 data = *p;
7694 if (!data) {
7695 /* allocate initial array */
7696 *p = data = malloc(2 * sizeof(void *));
7697 } else {
7698 for (c = 0; *data; data++, c++);
7699 }
7700 }
7701
7702 if (p) {
7703 /* enlarge the array */
7704 reallocated = realloc(*p, (c + 2) * sizeof(void *));
7705 if (!reallocated) {
7706 LOGMEM;
7707 return NULL;
7708 }
7709 *p = reallocated;
7710 data = *p;
7711 data[c + 1] = NULL;
7712 }
7713
7714 return &data[c];
7715}
7716
7717int
7718lyp_yin_parse_complex_ext(struct lys_module *mod, struct lys_ext_instance_complex *ext, struct lyxml_elem *yin,
7719 struct unres_schema *unres)
7720{
Radek Krejciaa9c5202017-02-15 16:10:14 +01007721 struct lyxml_elem *next, *node, *child;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007722 struct lys_type **type;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007723 void **pp, *p, *reallocated;
Radek Krejciaa9c5202017-02-15 16:10:14 +01007724 const char *value, *name;
7725 char *endptr, modifier;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007726 struct lyext_substmt *info;
7727 long int v;
Radek Krejci5496fae2017-02-10 13:26:48 +01007728 long long int ll;
7729 unsigned long u;
Radek Krejci7417a082017-02-16 11:07:59 +01007730 int i, j;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007731
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007732#define YIN_EXTCOMPLEX_GETPLACE(STMT, TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007733 p = lys_ext_complex_get_substmt(STMT, ext, &info); \
7734 if (!p) { \
7735 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
7736 goto error; \
7737 } \
7738 if (info->cardinality < LY_STMT_CARD_SOME && (*(TYPE*)p)) { \
7739 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
7740 goto error; \
7741 } \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007742 pp = NULL; i = 0; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007743 if (info->cardinality >= LY_STMT_CARD_SOME) { \
7744 /* there can be multiple instances */ \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007745 pp = p; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007746 if (!(*pp)) { \
7747 *pp = malloc(2 * sizeof(TYPE)); /* allocate initial array */ \
7748 } else { \
7749 for (i = 0; (*(TYPE**)pp)[i]; i++); \
7750 } \
7751 p = &(*(TYPE**)pp)[i]; \
7752 }
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007753#define YIN_EXTCOMPLEX_ENLARGE(TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007754 if (pp) { \
7755 /* enlarge the array */ \
7756 reallocated = realloc(*pp, (i + 2) * sizeof(TYPE*)); \
7757 if (!reallocated) { \
7758 LOGMEM; \
7759 goto error; \
7760 } \
7761 *pp = reallocated; \
7762 (*(TYPE**)pp)[i + 1] = 0; \
7763 }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007764#define YIN_EXTCOMPLEX_PARSE_SNODE(STMT, FUNC, ARGS...) \
7765 pp = (void**)yin_getplace_for_extcomplex_node(node, ext, STMT); \
7766 if (!pp) { goto error; } \
Radek Krejci7212e0a2017-03-08 15:58:22 +01007767 if (!FUNC(mod, (struct lys_node*)ext, node, ##ARGS, LYS_PARSE_OPT_CFG_NOINHERIT, unres)) { goto error; }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007768#define YIN_EXTCOMPLEX_PARSE_RESTR(STMT) \
7769 YIN_EXTCOMPLEX_GETPLACE(STMT, struct lys_restr*); \
7770 GETVAL(value, node, "value"); \
7771 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr)); \
7772 (*(struct lys_restr **)p)->expr = lydict_insert(mod->ctx, value, 0); \
7773 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) { \
7774 goto error; \
7775 } \
7776 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007777
Radek Krejci8d6b7422017-02-03 14:42:13 +01007778 LY_TREE_FOR_SAFE(yin->child, next, node) {
7779 if (!node->ns) {
7780 /* garbage */
7781 } else if (node->ns == yin->ns && (ext->flags & LYS_YINELEM) && ly_strequal(node->name, ext->def->argument, 1)) {
7782 /* we have the extension's argument */
7783 if (ext->arg_value) {
7784 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
7785 goto error;
7786 }
7787 ext->arg_value = node->content;
7788 node->content = NULL;
7789 } else if (strcmp(node->ns->value, LY_NSYIN)) {
7790 /* extension */
7791 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_SELF, 0, unres)) {
7792 goto error;
7793 }
7794 } else if (!strcmp(node->name, "description")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007795 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DESCRIPTION, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007796 goto error;
7797 }
7798 } else if (!strcmp(node->name, "reference")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007799 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REFERENCE, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007800 goto error;
7801 }
7802 } else if (!strcmp(node->name, "units")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007803 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_UNITS, 0, "name", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007804 goto error;
7805 }
7806 } else if (!strcmp(node->name, "type")) {
7807 type = (struct lys_type **)yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPE);
7808 if (!type) {
7809 goto error;
7810 }
7811 /* allocate type structure */
7812 (*type) = calloc(1, sizeof **type);
7813
7814 /* HACK for unres */
Radek Krejci63fc0962017-02-15 13:20:18 +01007815 lyxml_unlink(mod->ctx, node);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007816 (*type)->der = (struct lys_tpdf *)node;
7817 (*type)->parent = (struct lys_tpdf *)ext;
7818
7819 if (unres_schema_add_node(mod, unres, *type, UNRES_TYPE_DER_EXT, NULL) == -1) {
7820 (*type)->der = NULL;
7821 goto error;
7822 }
7823 continue; /* skip lyxml_free() */
Radek Krejci63fc0962017-02-15 13:20:18 +01007824 } else if (!strcmp(node->name, "typedef")) {
7825 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPEDEF);
7826 if (!pp) {
7827 goto error;
7828 }
7829 /* allocate typedef structure */
7830 (*pp) = calloc(1, sizeof(struct lys_tpdf));
7831
7832 if (fill_yin_typedef(mod, (struct lys_node *)ext, node, *((struct lys_tpdf **)pp), unres)) {
7833 goto error;
7834 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007835 } else if (!strcmp(node->name, "if-feature")) {
7836 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_IFFEATURE);
7837 if (!pp) {
7838 goto error;
7839 }
7840 /* allocate iffeature structure */
7841 (*pp) = calloc(1, sizeof(struct lys_iffeature));
7842
7843 if (fill_yin_iffeature((struct lys_node *)ext, 0, node, *((struct lys_iffeature **)pp), unres)) {
7844 goto error;
7845 }
7846 } else if (!strcmp(node->name, "status")) {
7847 p = yin_getplace_for_extcomplex_flags(node, ext, LY_STMT_STATUS, LYS_STATUS_MASK);
7848 if (!p) {
7849 goto error;
7850 }
7851
7852 GETVAL(value, node, "value");
7853 if (!strcmp(value, "current")) {
7854 *(uint16_t*)p |= LYS_STATUS_CURR;
7855 } else if (!strcmp(value, "deprecated")) {
7856 *(uint16_t*)p |= LYS_STATUS_DEPRC;
7857 } else if (!strcmp(value, "obsolete")) {
7858 *(uint16_t*)p |= LYS_STATUS_OBSLT;
7859 } else {
7860 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
7861 goto error;
7862 }
7863
7864 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, 0, unres)) {
7865 goto error;
7866 }
Radek Krejcic1885952017-02-07 09:37:51 +01007867 } else if (!strcmp(node->name, "config")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007868 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY, "true", "false", LYS_CONFIG_MASK,
Radek Krejcic1885952017-02-07 09:37:51 +01007869 LYS_CONFIG_W | LYS_CONFIG_SET, LYS_CONFIG_R | LYS_CONFIG_SET, unres)) {
7870 goto error;
7871 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007872 } else if (!strcmp(node->name, "argument")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007873 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ARGUMENT, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007874 goto error;
7875 }
7876 } else if (!strcmp(node->name, "default")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007877 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DEFAULT, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007878 goto error;
7879 }
Radek Krejcic1885952017-02-07 09:37:51 +01007880 } else if (!strcmp(node->name, "mandatory")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007881 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY,
Radek Krejcic1885952017-02-07 09:37:51 +01007882 "true", "false", LYS_MAND_MASK, LYS_MAND_TRUE, LYS_MAND_FALSE, unres)) {
7883 goto error;
7884 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007885 } else if (!strcmp(node->name, "error-app-tag")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007886 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRTAG, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007887 goto error;
7888 }
7889 } else if (!strcmp(node->name, "error-message")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007890 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRMSG, 1, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007891 goto error;
7892 }
7893 } else if (!strcmp(node->name, "prefix")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007894 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PREFIX, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007895 goto error;
7896 }
7897 } else if (!strcmp(node->name, "namespace")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007898 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_NAMESPACE, 0, "uri", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007899 goto error;
7900 }
7901 } else if (!strcmp(node->name, "presence")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007902 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PRESENCE, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007903 goto error;
7904 }
7905 } else if (!strcmp(node->name, "revision-date")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007906 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REVISIONDATE, 0, "date", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007907 goto error;
7908 }
7909 } else if (!strcmp(node->name, "key")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007910 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_KEY, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007911 goto error;
7912 }
7913 } else if (!strcmp(node->name, "base")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007914 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BASE, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007915 goto error;
7916 }
Radek Krejcic1885952017-02-07 09:37:51 +01007917 } else if (!strcmp(node->name, "ordered-by")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007918 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_ORDEREDBY,
7919 "user", "system", LYS_USERORDERED, LYS_USERORDERED, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007920 goto error;
7921 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007922 } else if (!strcmp(node->name, "belongs-to")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007923 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BELONGSTO, 0, "module", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007924 goto error;
7925 }
7926 } else if (!strcmp(node->name, "contact")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007927 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_CONTACT, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007928 goto error;
7929 }
7930 } else if (!strcmp(node->name, "organization")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007931 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ORGANIZATION, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007932 goto error;
7933 }
7934 } else if (!strcmp(node->name, "path")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007935 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PATH, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007936 goto error;
7937 }
Radek Krejcic1885952017-02-07 09:37:51 +01007938 } else if (!strcmp(node->name, "require-instance")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007939 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_REQINSTANCE, "true", "false", unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007940 goto error;
7941 }
7942 } else if (!strcmp(node->name, "modifier")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007943 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_MODIFIER, "invert-match", NULL, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007944 goto error;
7945 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007946 } else if (!strcmp(node->name, "fraction-digits")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007947 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_DIGITS, uint8_t);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007948
7949 GETVAL(value, node, "value");
7950 v = strtol(value, NULL, 10);
7951
7952 /* range check */
7953 if (v < 1 || v > 18) {
7954 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
7955 goto error;
7956 }
7957
7958 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, i, unres)) {
7959 goto error;
7960 }
7961
7962 /* store the value */
7963 (*(uint8_t *)p) = (uint8_t)v;
7964
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007965 YIN_EXTCOMPLEX_ENLARGE(uint8_t);
Radek Krejci5496fae2017-02-10 13:26:48 +01007966 } else if (!strcmp(node->name, "max-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007967 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MAX, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007968
7969 GETVAL(value, node, "value");
7970 while (isspace(value[0])) {
7971 value++;
7972 }
7973
7974 if (!strcmp(value, "unbounded")) {
7975 u = 0;
7976 } else {
7977 /* convert it to uint32_t */
7978 errno = 0; endptr = NULL;
7979 u = strtoul(value, &endptr, 10);
7980 if (*endptr || value[0] == '-' || errno || u == 0 || u > UINT32_MAX) {
7981 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007982 goto error;
7983 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007984 }
Radek Krejci5496fae2017-02-10 13:26:48 +01007985
7986 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
7987 goto error;
7988 }
7989
7990 /* store the value */
Radek Krejcif8d05c22017-02-10 15:33:35 +01007991 *(uint32_t **)p = malloc(sizeof(uint32_t));
7992 (**(uint32_t **)p) = (uint32_t)u;
Radek Krejci5496fae2017-02-10 13:26:48 +01007993
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007994 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007995 } else if (!strcmp(node->name, "min-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007996 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MIN, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007997
7998 GETVAL(value, node, "value");
7999 while (isspace(value[0])) {
8000 value++;
8001 }
8002
8003 /* convert it to uint32_t */
8004 errno = 0;
8005 endptr = NULL;
8006 u = strtoul(value, &endptr, 10);
8007 if (*endptr || value[0] == '-' || errno || u > UINT32_MAX) {
8008 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
8009 goto error;
8010 }
8011
8012 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
8013 goto error;
8014 }
8015
8016 /* store the value */
Radek Krejcif8d05c22017-02-10 15:33:35 +01008017 *(uint32_t **)p = malloc(sizeof(uint32_t));
8018 (**(uint32_t **)p) = (uint32_t)u;
Radek Krejci5496fae2017-02-10 13:26:48 +01008019
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008020 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci06a9aa02017-02-17 10:50:24 +01008021 } else if (!strcmp(node->name, "value")) {
PavolVican2ed9f4e2017-02-16 00:08:45 +01008022 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_VALUE, int32_t*);
8023
8024 GETVAL(value, node, "value");
8025 while (isspace(value[0])) {
8026 value++;
8027 }
8028
8029 /* convert it to int32_t */
Radek Krejci9326fc02017-02-16 09:57:40 +01008030 ll = strtoll(value, NULL, 10);
PavolVican2ed9f4e2017-02-16 00:08:45 +01008031
8032 /* range check */
Radek Krejci9326fc02017-02-16 09:57:40 +01008033 if (ll < INT32_MIN || ll > INT32_MAX) {
PavolVican2ed9f4e2017-02-16 00:08:45 +01008034 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
8035 goto error;
8036 }
8037
8038 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_VALUE, i, unres)) {
8039 goto error;
8040 }
8041
8042 /* store the value */
8043 *(int32_t **)p = malloc(sizeof(int32_t));
Radek Krejci9326fc02017-02-16 09:57:40 +01008044 (**(int32_t **)p) = (int32_t)ll;
PavolVican2ed9f4e2017-02-16 00:08:45 +01008045
8046 YIN_EXTCOMPLEX_ENLARGE(int32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008047 } else if (!strcmp(node->name, "position")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008048 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_POSITION, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01008049
8050 GETVAL(value, node, "value");
8051 ll = strtoll(value, NULL, 10);
8052
8053 /* range check */
8054 if (ll < 0 || ll > UINT32_MAX) {
8055 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
8056 goto error;
8057 }
8058
8059 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_POSITION, i, unres)) {
8060 goto error;
8061 }
8062
8063 /* store the value */
Radek Krejcif8d05c22017-02-10 15:33:35 +01008064 *(uint32_t **)p = malloc(sizeof(uint32_t));
8065 (**(uint32_t **)p) = (uint32_t)ll;
Radek Krejci5496fae2017-02-10 13:26:48 +01008066
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008067 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci37f9ba32017-02-10 16:50:35 +01008068 } else if (!strcmp(node->name, "module")) {
8069 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MODULE);
8070 if (!pp) {
8071 goto error;
8072 }
8073
8074 *(struct lys_module **)pp = yin_read_module_(mod->ctx, node, NULL, mod->implemented);
8075 if (!(*pp)) {
8076 goto error;
8077 }
Radek Krejcic5cc5302017-02-16 10:07:46 +01008078 } else if (!strcmp(node->name, "when")) {
8079 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_WHEN, struct lys_when*);
8080
8081 *(struct lys_when**)p = read_yin_when(mod, node, unres);
8082 if (!*(struct lys_when**)p) {
8083 goto error;
8084 }
8085
8086 YIN_EXTCOMPLEX_ENLARGE(struct lys_when*);
Radek Krejci7417a082017-02-16 11:07:59 +01008087 } else if (!strcmp(node->name, "revision")) {
8088 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_REVISION, struct lys_revision*);
8089
8090 *(struct lys_revision**)p = calloc(1, sizeof(struct lys_revision));
8091 if (fill_yin_revision(mod, node, *(struct lys_revision**)p, unres)) {
8092 goto error;
8093 }
8094
8095 /* check uniqueness of the revision dates - not required by RFC */
8096 if (pp) {
8097 for (j = 0; j < i; j++) {
8098 if (!strcmp((*(struct lys_revision***)pp)[j]->date, (*(struct lys_revision**)p)->date)) {
8099 LOGWRN("Module's revisions are not unique (%s).", (*(struct lys_revision**)p)->date);
8100 }
8101 }
8102 }
8103
8104 YIN_EXTCOMPLEX_ENLARGE(struct lys_revision*);
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008105 } else if (!strcmp(node->name, "unique")) {
8106 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_UNIQUE, struct lys_unique*);
8107
8108 *(struct lys_unique**)p = calloc(1, sizeof(struct lys_unique));
8109 if (fill_yin_unique(mod, (struct lys_node*)ext, node, *(struct lys_unique**)p, unres)) {
8110 goto error;
8111 }
8112
8113 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_UNIQUE, i, unres)) {
8114 goto error;
8115 }
8116 YIN_EXTCOMPLEX_ENLARGE(struct lys_unique*);
Radek Krejcif95b6292017-02-13 15:57:37 +01008117 } else if (!strcmp(node->name, "action")) {
8118 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ACTION, read_yin_rpc_action);
8119 } else if (!strcmp(node->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008120 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYDATA, read_yin_anydata, LYS_ANYDATA);
Radek Krejcif95b6292017-02-13 15:57:37 +01008121 } else if (!strcmp(node->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008122 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYXML, read_yin_anydata, LYS_ANYXML);
Radek Krejcif95b6292017-02-13 15:57:37 +01008123 } else if (!strcmp(node->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008124 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CASE, read_yin_case);
Radek Krejcif95b6292017-02-13 15:57:37 +01008125 } else if (!strcmp(node->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008126 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CHOICE, read_yin_choice);
Radek Krejcif95b6292017-02-13 15:57:37 +01008127 } else if (!strcmp(node->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008128 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CONTAINER, read_yin_container);
Radek Krejcif95b6292017-02-13 15:57:37 +01008129 } else if (!strcmp(node->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008130 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_GROUPING, read_yin_grouping);
Radek Krejcif95b6292017-02-13 15:57:37 +01008131 } else if (!strcmp(node->name, "output")) {
8132 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_OUTPUT, read_yin_input_output);
8133 } else if (!strcmp(node->name, "input")) {
8134 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_INPUT, read_yin_input_output);
8135 } else if (!strcmp(node->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008136 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAF, read_yin_leaf);
Radek Krejcif95b6292017-02-13 15:57:37 +01008137 } else if (!strcmp(node->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008138 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAFLIST, read_yin_leaflist);
Radek Krejcif95b6292017-02-13 15:57:37 +01008139 } else if (!strcmp(node->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008140 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LIST, read_yin_list);
Radek Krejcif95b6292017-02-13 15:57:37 +01008141 } else if (!strcmp(node->name, "notification")) {
8142 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_NOTIFICATION, read_yin_notif);
8143 } else if (!strcmp(node->name, "uses")) {
8144 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_USES, read_yin_uses);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008145 } else if (!strcmp(node->name, "length")) {
8146 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_LENGTH);
8147 } else if (!strcmp(node->name, "must")) {
8148 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MUST);
8149 if (!pp) {
8150 goto error;
8151 }
8152 /* allocate structure for must */
8153 (*pp) = calloc(1, sizeof(struct lys_restr));
8154
8155 if (fill_yin_must(mod, node, *((struct lys_restr **)pp), unres)) {
8156 goto error;
8157 }
8158 } else if (!strcmp(node->name, "pattern")) {
8159 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_PATTERN, struct lys_restr*);
8160 GETVAL(value, node, "value");
8161 if (lyp_check_pattern(value, NULL)) {
8162 goto error;
8163 }
8164
8165 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr));
8166 (*(struct lys_restr **)p)->expr = lydict_insert(mod->ctx, value, 0);
8167
8168 modifier = 0x06; /* ACK */
8169 if (mod->version >= 2) {
8170 name = NULL;
8171 LY_TREE_FOR(node->child, child) {
8172 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
8173 if (name) {
8174 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
8175 goto error;
8176 }
8177
8178 GETVAL(name, child, "value");
8179 if (!strcmp(name, "invert-match")) {
8180 modifier = 0x15; /* NACK */
8181 } else {
8182 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
8183 goto error;
8184 }
8185 /* get extensions of the modifier */
8186 if (lyp_yin_parse_subnode_ext(mod, *(struct lys_restr **)p, LYEXT_PAR_RESTR, child,
8187 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
8188 goto error;
8189 }
8190 }
8191 }
8192 }
8193
8194 /* store the value: modifier byte + value + terminating NULL byte */
8195 (*(struct lys_restr **)p)->expr = malloc((strlen(value) + 2) * sizeof(char));
8196 ((char *)(*(struct lys_restr **)p)->expr)[0] = modifier;
8197 strcpy(&((char *)(*(struct lys_restr **)p)->expr)[1], value);
8198 lydict_insert_zc(mod->ctx, (char *)(*(struct lys_restr **)p)->expr);
8199
8200 /* get possible sub-statements */
8201 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) {
8202 goto error;
8203 }
8204
8205 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
8206 } else if (!strcmp(node->name, "range")) {
8207 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_RANGE);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008208 } else {
Radek Krejci06a9aa02017-02-17 10:50:24 +01008209 LOGERR(LY_SUCCESS, "Extension's substatement \"%s\" not supported.", node->name);
8210 //LOGERR(LY_EINT, "Extension's substatement \"%s\" not supported.", node->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008211 //return EXIT_FAILURE;
8212 }
8213 lyxml_free(mod->ctx, node);
8214 }
8215
PavolVicanc4b798e2017-02-20 23:15:27 +01008216 if (ext->substmt && lyp_mand_check_ext(ext, yin->name)) {
8217 return EXIT_FAILURE;
Radek Krejci06a9aa02017-02-17 10:50:24 +01008218 }
8219
Radek Krejci8d6b7422017-02-03 14:42:13 +01008220 return EXIT_SUCCESS;
8221
8222error:
8223 return EXIT_FAILURE;
8224}