blob: 5614f94b653b1c1704140247b2d11d3afee56b41 [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 */
Radek Krejci7212e0a2017-03-08 15:58:22 +01003150 if (!(options & LYS_PARSE_OPT_INGRP) && aug->when &&
3151 (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02003152 goto error;
3153 }
3154
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003155 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02003156
3157error:
3158
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003159 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02003160}
3161
Michal Vasko0d343d12015-08-24 14:57:36 +02003162/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003163static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02003164fill_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 +02003165{
Radek Krejci363bd4a2016-07-29 14:30:20 +02003166 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003167 struct lyxml_elem *sub, *next;
3168 const char *value;
3169 char *endptr;
3170 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01003171 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003172 int r;
3173 unsigned long int val;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003174 void *reallocated;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003175
Radek Krejci363bd4a2016-07-29 14:30:20 +02003176 assert(uses);
3177 module = uses->module; /* shorthand */
3178
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003179 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003180 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02003181 if (!rfn->target_name) {
3182 goto error;
3183 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003184
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003185 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003186 if (!sub->ns) {
3187 /* garbage */
3188 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01003189 /* extension */
3190 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003191 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02003192
Radek Krejci411b1bf2017-01-23 16:40:05 +01003193 } else if (!strcmp(sub->name, "description")) {
3194 if (rfn->dsc) {
3195 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3196 goto error;
3197 }
3198
Radek Krejci8d6b7422017-02-03 14:42:13 +01003199 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003200 goto error;
3201 }
3202
3203 rfn->dsc = read_yin_subnode(module->ctx, sub, "text");
3204 if (!rfn->dsc) {
3205 goto error;
3206 }
3207 } else if (!strcmp(sub->name, "reference")) {
3208 if (rfn->ref) {
3209 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3210 goto error;
3211 }
3212
Radek Krejci8d6b7422017-02-03 14:42:13 +01003213 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003214 goto error;
3215 }
3216
3217 rfn->ref = read_yin_subnode(module->ctx, sub, "text");
3218 if (!rfn->ref) {
3219 goto error;
3220 }
3221 } else if (!strcmp(sub->name, "config")) {
3222 if (rfn->flags & LYS_CONFIG_MASK) {
3223 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3224 goto error;
3225 }
3226 GETVAL(value, sub, "value");
3227 if (!strcmp(value, "false")) {
3228 rfn->flags |= LYS_CONFIG_R;
3229 } else if (!strcmp(value, "true")) {
3230 rfn->flags |= LYS_CONFIG_W;
3231 } else {
3232 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3233 goto error;
3234 }
3235 rfn->flags |= LYS_CONFIG_SET;
3236
Radek Krejci8d6b7422017-02-03 14:42:13 +01003237 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003238 goto error;
3239 }
Radek Krejcie534c132016-11-23 13:32:31 +01003240 } else if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02003241 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02003242
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003243 /* check possibility of statements combination */
3244 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02003245 if (c_dflt) {
3246 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003247 if (module->version < 2) {
3248 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3249 goto error;
3250 }
Radek Krejci200bf712016-08-16 17:11:04 +02003251 rfn->target_type &= LYS_LEAFLIST;
3252 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003253 if (module->version < 2) {
3254 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
3255 } else {
3256 /* YANG 1.1 */
3257 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
3258 }
Radek Krejci200bf712016-08-16 17:11:04 +02003259 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003260 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003261 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3262 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003263 goto error;
3264 }
3265 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003266 if (module->version < 2) {
3267 rfn->target_type = LYS_LEAF | LYS_CHOICE;
3268 } else {
3269 /* YANG 1.1 */
3270 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
3271 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003272 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003273
Radek Krejci8d6b7422017-02-03 14:42:13 +01003274 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 +01003275 goto error;
3276 }
Radek Krejci200bf712016-08-16 17:11:04 +02003277 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003278 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003279 } else if (!strcmp(sub->name, "mandatory")) {
3280 /* leaf, choice or anyxml */
3281 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003282 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003283 goto error;
3284 }
3285 /* just checking the flags in leaf is not sufficient, we would allow
3286 * multiple mandatory statements with the "false" value
3287 */
3288 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003289
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003290 /* check possibility of statements combination */
3291 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003292 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003293 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003294 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3295 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003296 goto error;
3297 }
3298 } else {
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 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003302 GETVAL(value, sub, "value");
3303 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003304 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003305 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003306 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003307 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003308 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003309 goto error;
3310 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003311 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003312 goto error;
3313 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003314 } else if (!strcmp(sub->name, "min-elements")) {
3315 /* list or leaf-list */
3316 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003317 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003318 goto error;
3319 }
3320 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003321
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003322 /* check possibility of statements combination */
3323 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003324 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003325 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003326 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3327 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003328 goto error;
3329 }
3330 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003331 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003332 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003333
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003334 GETVAL(value, sub, "value");
3335 while (isspace(value[0])) {
3336 value++;
3337 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003338
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003339 /* convert it to uint32_t */
3340 errno = 0;
3341 endptr = NULL;
3342 val = strtoul(value, &endptr, 10);
3343 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003344 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003345 goto error;
3346 }
3347 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003348 rfn->flags |= LYS_RFN_MINSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003349
Radek Krejci8d6b7422017-02-03 14:42:13 +01003350 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003351 goto error;
3352 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003353 } else if (!strcmp(sub->name, "max-elements")) {
3354 /* list or leaf-list */
3355 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003356 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003357 goto error;
3358 }
3359 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003360
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003361 /* check possibility of statements combination */
3362 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003363 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003364 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003365 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3366 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003367 goto error;
3368 }
3369 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003370 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003371 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003372
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003373 GETVAL(value, sub, "value");
3374 while (isspace(value[0])) {
3375 value++;
3376 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003377
Radek Krejci0d7b2472016-02-12 11:11:03 +01003378 if (!strcmp(value, "unbounded")) {
3379 rfn->mod.list.max = 0;
3380 } else {
3381 /* convert it to uint32_t */
3382 errno = 0;
3383 endptr = NULL;
3384 val = strtoul(value, &endptr, 10);
3385 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003386 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003387 goto error;
3388 }
3389 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003390 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003391 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003392
Radek Krejci8d6b7422017-02-03 14:42:13 +01003393 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003394 goto error;
3395 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003396 } else if (!strcmp(sub->name, "presence")) {
3397 /* container */
3398 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003399 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003400 goto error;
3401 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003402
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003403 /* check possibility of statements combination */
3404 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003405 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003406 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003407 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3408 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003409 goto error;
3410 }
3411 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003412 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003413 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003414
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003415 GETVAL(value, sub, "value");
3416 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcifdc0d702017-01-23 15:58:38 +01003417
Radek Krejci8d6b7422017-02-03 14:42:13 +01003418 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003419 goto error;
3420 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003421 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02003422 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003423 /* check possibility of statements combination */
3424 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003425 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003426 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003427 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3428 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003429 goto error;
3430 }
3431 } else {
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 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003434
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003435 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003436 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003437
Radek Krejci363bd4a2016-07-29 14:30:20 +02003438 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
3439 /* leaf, leaf-list, list, container or anyxml */
3440 /* check possibility of statements combination */
3441 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003442 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003443 if (!rfn->target_type) {
3444 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3445 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
3446 goto error;
3447 }
3448 } else {
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 }
3451
3452 c_ftrs++;
3453 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003454 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003455 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003456 goto error;
3457 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003458
Michal Vasko345da0a2015-12-02 10:35:55 +01003459 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003460 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003461
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003462 /* process nodes with cardinality of 0..n */
3463 if (c_must) {
3464 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003465 if (!rfn->must) {
3466 LOGMEM;
3467 goto error;
3468 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003469 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02003470 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02003471 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003472 if (!rfn->iffeature) {
3473 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02003474 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003475 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003476 }
Radek Krejci200bf712016-08-16 17:11:04 +02003477 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003478 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Radek Krejci200bf712016-08-16 17:11:04 +02003479 if (!rfn->dflt) {
3480 LOGMEM;
3481 goto error;
3482 }
3483 }
Radek Krejcie534c132016-11-23 13:32:31 +01003484 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003485 /* some extensions may be already present from the substatements */
3486 reallocated = realloc(rfn->ext, (c_ext + rfn->ext_size) * sizeof *rfn->ext);
3487 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003488 LOGMEM;
3489 goto error;
3490 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01003491 rfn->ext = reallocated;
3492
3493 /* init memory */
3494 memset(&rfn->ext[rfn->ext_size], 0, c_ext * sizeof *rfn->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003495 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003496
Radek Krejcie534c132016-11-23 13:32:31 +01003497 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3498 if (strcmp(sub->ns->value, LY_NSYIN)) {
3499 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003500 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 +01003501 rfn->ext_size++;
3502 if (r) {
3503 goto error;
3504 }
3505 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003506 r = fill_yin_iffeature(uses, 0, sub, &rfn->iffeature[rfn->iffeature_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003507 rfn->iffeature_size++;
3508 if (r) {
3509 goto error;
3510 }
Radek Krejci200bf712016-08-16 17:11:04 +02003511 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01003512 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003513 rfn->must_size++;
3514 if (r) {
3515 goto error;
3516 }
Radek Krejci200bf712016-08-16 17:11:04 +02003517 } else { /* default */
3518 GETVAL(value, sub, "value");
3519
3520 /* check for duplicity */
3521 for (r = 0; r < rfn->dflt_size; r++) {
3522 if (ly_strequal(rfn->dflt[r], value, 1)) {
3523 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3524 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
3525 goto error;
3526 }
3527 }
3528 rfn->dflt[rfn->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02003529 }
3530 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003531
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003532 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003533
3534error:
3535
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003536 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003537}
3538
Michal Vasko0d343d12015-08-24 14:57:36 +02003539/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003540static int
Radek Krejcie534c132016-11-23 13:32:31 +01003541fill_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 +02003542{
Radek Krejcie534c132016-11-23 13:32:31 +01003543 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003544 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003545 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003546 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003547
Radek Krejcie534c132016-11-23 13:32:31 +01003548 /* init */
3549 memset(&exts, 0, sizeof exts);
3550
3551 LY_TREE_FOR_SAFE(yin->child, next, child) {
3552 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003553 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003554 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003555 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3556 /* extension */
3557 c_ext++;
3558 lyxml_unlink_elem(module->ctx, child, 2);
3559 lyxml_add_child(module->ctx, &exts, child);
3560 } else if (!strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003561 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01003562 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003563 goto error;
3564 }
3565 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01003566
Radek Krejci8d6b7422017-02-03 14:42:13 +01003567 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003568 goto error;
3569 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003570 } else if (!strcmp(child->name, "revision-date")) {
3571 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02003572 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3573 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003574 }
3575 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003576 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003577 goto error;
3578 }
3579 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003580
Radek Krejci8d6b7422017-02-03 14:42:13 +01003581 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003582 goto error;
3583 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003584 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003585 if (imp->dsc) {
3586 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3587 goto error;
3588 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003589 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003590 goto error;
3591 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003592 imp->dsc = read_yin_subnode(module->ctx, child, "text");
3593 if (!imp->dsc) {
3594 goto error;
3595 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003596 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003597 if (imp->ref) {
3598 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3599 goto error;
3600 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003601 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003602 goto error;
3603 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003604 imp->ref = read_yin_subnode(module->ctx, child, "text");
3605 if (!imp->ref) {
3606 goto error;
3607 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003608 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003609 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003610 goto error;
3611 }
3612 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003613
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003614 /* check mandatory information */
3615 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003616 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003617 goto error;
3618 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003619
Radek Krejcie534c132016-11-23 13:32:31 +01003620 /* process extensions */
3621 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003622 /* some extensions may be already present from the substatements */
3623 reallocated = realloc(imp->ext, (c_ext + imp->ext_size) * sizeof *imp->ext);
3624 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003625 LOGMEM;
3626 goto error;
3627 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003628 imp->ext = reallocated;
3629
3630 /* init memory */
3631 memset(&imp->ext[imp->ext_size], 0, c_ext * sizeof *imp->ext);
3632
Radek Krejcie534c132016-11-23 13:32:31 +01003633 LY_TREE_FOR_SAFE(exts.child, next, child) {
3634 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003635 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 +01003636 imp->ext_size++;
3637 if (r) {
3638 goto error;
3639 }
3640 }
3641 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003642
Radek Krejcie534c132016-11-23 13:32:31 +01003643 GETVAL(value, yin, "module");
Pavol Vicane994fda2016-03-22 10:47:58 +01003644 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02003645
3646error:
3647
Radek Krejcie534c132016-11-23 13:32:31 +01003648 while (exts.child) {
3649 lyxml_free(module->ctx, exts.child);
3650 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003651 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02003652}
3653
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003654/* logs directly
3655 * returns:
3656 * 0 - inc successfully filled
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003657 * -1 - error
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003658 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003659static int
Michal Vasko5ff78822016-02-12 09:33:31 +01003660fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
3661 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02003662{
Radek Krejcie534c132016-11-23 13:32:31 +01003663 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003664 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003665 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003666 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003667
Radek Krejcie534c132016-11-23 13:32:31 +01003668 /* init */
3669 memset(&exts, 0, sizeof exts);
3670
3671 LY_TREE_FOR_SAFE(yin->child, next, child) {
3672 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003673 /* garbage */
3674 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003675 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3676 /* extension */
3677 c_ext++;
3678 lyxml_unlink_elem(module->ctx, child, 2);
3679 lyxml_add_child(module->ctx, &exts, child);
3680 } else if (!strcmp(child->name, "revision-date")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003681 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003682 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003683 goto error;
3684 }
3685 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003686 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003687 goto error;
3688 }
3689 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003690
Radek Krejci8d6b7422017-02-03 14:42:13 +01003691 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003692 goto error;
3693 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003694 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003695 if (inc->dsc) {
3696 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3697 goto error;
3698 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003699 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003700 goto error;
3701 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003702 inc->dsc = read_yin_subnode(module->ctx, child, "text");
3703 if (!inc->dsc) {
3704 goto error;
3705 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003706 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003707 if (inc->ref) {
3708 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3709 goto error;
3710 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003711 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003712 goto error;
3713 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003714 inc->ref = read_yin_subnode(module->ctx, child, "text");
3715 if (!inc->ref) {
3716 goto error;
3717 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003718 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003719 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003720 goto error;
3721 }
3722 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003723
Radek Krejcie534c132016-11-23 13:32:31 +01003724 /* process extensions */
3725 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003726 /* some extensions may be already present from the substatements */
3727 reallocated = realloc(inc->ext, (c_ext + inc->ext_size) * sizeof *inc->ext);
3728 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003729 LOGMEM;
3730 goto error;
3731 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003732 inc->ext = reallocated;
3733
3734 /* init memory */
3735 memset(&inc->ext[inc->ext_size], 0, c_ext * sizeof *inc->ext);
3736
Radek Krejcie534c132016-11-23 13:32:31 +01003737 LY_TREE_FOR_SAFE(exts.child, next, child) {
3738 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003739 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 +01003740 inc->ext_size++;
3741 if (r) {
3742 goto error;
3743 }
3744 }
3745 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003746
Radek Krejcie534c132016-11-23 13:32:31 +01003747 GETVAL(value, yin, "module");
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003748 return lyp_check_include(submodule ? (struct lys_module *)submodule : module, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02003749
3750error:
3751
Radek Krejci83e3f5b2016-06-24 14:55:25 +02003752 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02003753}
3754
Michal Vasko0d343d12015-08-24 14:57:36 +02003755/* logs directly
3756 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003757 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02003758 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02003759 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003760 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003761static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01003762read_yin_common(struct lys_module *module, struct lys_node *parent, void *stmt, LYEXT_PAR stmt_type,
3763 struct lyxml_elem *xmlnode, int opt, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003764{
Radek Krejci07d0fb92017-01-13 14:11:05 +01003765 struct lys_node *node = stmt;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003766 const char *value;
3767 struct lyxml_elem *sub, *next;
3768 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003770 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003771 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003772 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003773
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003774 if (opt & OPT_IDENT) {
3775 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01003776 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003777 goto error;
3778 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003779 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003780 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003781
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003782 /* process local parameters */
3783 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003784 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003785 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003786 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02003787 continue;
3788 }
3789 if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejci6ff885d2017-01-03 14:06:22 +01003790 /* possibly an extension, keep the node for later processing, so skipping lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003791 continue;
3792 }
3793
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003794 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003795 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003796 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003797 goto error;
3798 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003799
Radek Krejci8d6b7422017-02-03 14:42:13 +01003800 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003801 goto error;
3802 }
3803
Radek Krejci1d82ef62015-08-07 14:44:40 +02003804 node->dsc = read_yin_subnode(ctx, sub, "text");
3805 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003806 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003807 }
3808 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003809 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003810 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003811 goto error;
3812 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003813
Radek Krejci8d6b7422017-02-03 14:42:13 +01003814 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003815 goto error;
3816 }
3817
Radek Krejci1d82ef62015-08-07 14:44:40 +02003818 node->ref = read_yin_subnode(ctx, sub, "text");
3819 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003820 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003821 }
3822 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003823 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003824 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003825 goto error;
3826 }
3827 GETVAL(value, sub, "value");
3828 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003829 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003830 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003831 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003832 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003833 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003834 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003835 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003836 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003837 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003838
Radek Krejci8d6b7422017-02-03 14:42:13 +01003839 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_STATUS, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003840 goto error;
3841 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003842 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3843 if (opt & OPT_CFG_PARSE) {
3844 if (node->flags & LYS_CONFIG_MASK) {
3845 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
3846 goto error;
3847 }
3848 GETVAL(value, sub, "value");
3849 if (!strcmp(value, "false")) {
3850 node->flags |= LYS_CONFIG_R;
3851 } else if (!strcmp(value, "true")) {
3852 node->flags |= LYS_CONFIG_W;
3853 } else {
3854 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3855 goto error;
3856 }
3857 node->flags |= LYS_CONFIG_SET;
Radek Krejci07d0fb92017-01-13 14:11:05 +01003858
Radek Krejci8d6b7422017-02-03 14:42:13 +01003859 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003860 goto error;
3861 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003862 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003863 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003864 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003865 continue;
3866 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003867 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003868 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003869
Michal Vaskoe022a562016-09-27 14:24:15 +02003870 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003871 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02003872 if (parent) {
3873 node->flags |= parent->flags & LYS_CONFIG_MASK;
3874 } else if (!parent) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003875 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003876 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003877 }
3878 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003879
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003880 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02003881
3882error:
3883
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003884 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003885}
3886
Michal Vasko0d343d12015-08-24 14:57:36 +02003887/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003888static struct lys_when *
Radek Krejci5323b492017-01-16 15:40:11 +01003889read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003890{
Radek Krejci76512572015-08-04 09:47:08 +02003891 struct lys_when *retval = NULL;
Radek Krejci5323b492017-01-16 15:40:11 +01003892 struct lyxml_elem *child, *next;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003893 const char *value;
3894
3895 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01003896 if (!retval) {
3897 LOGMEM;
3898 return NULL;
3899 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003900
3901 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01003902 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02003903 if (!retval->cond) {
3904 goto error;
3905 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003906
Radek Krejci5323b492017-01-16 15:40:11 +01003907 LY_TREE_FOR_SAFE(yin->child, next, child) {
3908 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003909 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003910 continue;
Radek Krejci5323b492017-01-16 15:40:11 +01003911 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3912 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01003913 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003914 goto error;
3915 }
3916 } else if (!strcmp(child->name, "description")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003917 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003918 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003919 goto error;
3920 }
Radek Krejci5323b492017-01-16 15:40:11 +01003921
Radek Krejci8d6b7422017-02-03 14:42:13 +01003922 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003923 goto error;
3924 }
3925
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003926 retval->dsc = read_yin_subnode(module->ctx, child, "text");
3927 if (!retval->dsc) {
3928 goto error;
3929 }
3930 } else if (!strcmp(child->name, "reference")) {
3931 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003932 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003933 goto error;
3934 }
Radek Krejci5323b492017-01-16 15:40:11 +01003935
Radek Krejci8d6b7422017-02-03 14:42:13 +01003936 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003937 goto error;
3938 }
3939
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003940 retval->ref = read_yin_subnode(module->ctx, child, "text");
3941 if (!retval->ref) {
3942 goto error;
3943 }
3944 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003945 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003946 goto error;
3947 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003948 }
3949
3950 return retval;
3951
3952error:
3953
Michal Vasko0308dd62015-10-07 09:14:40 +02003954 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003955 return NULL;
3956}
3957
Michal Vasko0d343d12015-08-24 14:57:36 +02003958/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003959static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01003960read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02003961 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02003962{
Michal Vasko29fc0182015-08-24 15:02:39 +02003963 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003964 struct lys_node_case *cs;
3965 struct lys_node *retval, *node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01003966 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01003967 void *reallocated;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003968
Radek Krejcie867c852015-08-27 09:52:34 +02003969 /* init */
3970 memset(&root, 0, sizeof root);
3971
Radek Krejci1d82ef62015-08-07 14:44:40 +02003972 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01003973 if (!cs) {
3974 LOGMEM;
3975 return NULL;
3976 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003977 cs->nodetype = LYS_CASE;
3978 cs->prev = (struct lys_node *)cs;
3979 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003980
Radek Krejci07d0fb92017-01-13 14:11:05 +01003981 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01003982 OPT_IDENT | OPT_MODULE | (!(options & LYS_PARSE_OPT_CFG_MASK) ? OPT_CFG_INHERIT : 0), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003983 goto error;
3984 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003985
Michal Vasko3e3228d2017-02-24 14:55:32 +01003986 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02003987
Michal Vasko3a0043f2015-08-12 12:11:30 +02003988 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003989 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003990 goto error;
3991 }
3992
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003993 /* process choice's specific children */
3994 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01003995 if (strcmp(sub->ns->value, LY_NSYIN)) {
3996 /* extension */
3997 c_ext++;
3998 } else if (!strcmp(sub->name, "container") ||
Michal Vasko29fc0182015-08-24 15:02:39 +02003999 !strcmp(sub->name, "leaf-list") ||
4000 !strcmp(sub->name, "leaf") ||
4001 !strcmp(sub->name, "list") ||
4002 !strcmp(sub->name, "uses") ||
4003 !strcmp(sub->name, "choice") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01004004 !strcmp(sub->name, "anyxml") ||
4005 !strcmp(sub->name, "anydata")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02004006
Michal Vaskof3930de2015-10-22 12:03:59 +02004007 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02004008 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004009 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02004010 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004011 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004012 if (cs->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004013 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004014 goto error;
4015 }
4016
Radek Krejci5323b492017-01-16 15:40:11 +01004017 cs->when = read_yin_when(module, sub, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004018 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004019 goto error;
4020 }
Michal Vasko29fc0182015-08-24 15:02:39 +02004021
Michal Vasko345da0a2015-12-02 10:35:55 +01004022 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004023 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004024 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004025 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004026 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004027 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004028
Radek Krejci3cf9e222015-06-18 11:37:50 +02004029 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004030 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
4031 if (!cs->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004032 LOGMEM;
4033 goto error;
4034 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004035 }
Radek Krejcie534c132016-11-23 13:32:31 +01004036 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004037 /* some extensions may be already present from the substatements */
4038 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4039 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004040 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004041 goto error;
4042 }
Radek Krejci21c81652017-01-23 10:42:55 +01004043 retval->ext = reallocated;
4044
4045 /* init memory */
4046 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004047 }
Radek Krejci21c81652017-01-23 10:42:55 +01004048
Radek Krejcie534c132016-11-23 13:32:31 +01004049 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4050 if (strcmp(sub->ns->value, LY_NSYIN)) {
4051 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004052 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 +01004053 retval->ext_size++;
4054 if (ret) {
4055 goto error;
4056 }
4057 } else {
4058 /* if-feature */
4059 ret = fill_yin_iffeature(retval, 0, sub, &cs->iffeature[cs->iffeature_size], unres);
4060 cs->iffeature_size++;
4061 if (ret) {
4062 goto error;
4063 }
4064 }
4065 }
Radek Krejcib388c152015-06-04 17:03:03 +02004066
Michal Vasko29fc0182015-08-24 15:02:39 +02004067 /* last part - process data nodes */
4068 LY_TREE_FOR_SAFE(root.child, next, sub) {
4069 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004070 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004071 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004072 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004073 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004074 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004075 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004076 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004077 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004078 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004079 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004080 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004081 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004082 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004083 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004084 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004085 }
4086 if (!node) {
4087 goto error;
4088 }
4089
Michal Vasko345da0a2015-12-02 10:35:55 +01004090 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02004091 }
4092
Michal Vasko508a50d2016-09-07 14:50:33 +02004093 /* check XPath dependencies */
Radek Krejci7212e0a2017-03-08 15:58:22 +01004094 if (!(options & LYS_PARSE_OPT_INGRP) && cs->when &&
4095 (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02004096 goto error;
4097 }
4098
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004099 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004100
4101error:
4102
Michal Vasko29fc0182015-08-24 15:02:39 +02004103 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004104 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02004105 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004106 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02004107
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004108 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004109}
4110
Michal Vasko0d343d12015-08-24 14:57:36 +02004111/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004112static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004113read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskoe022a562016-09-27 14:24:15 +02004114 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004115{
Radek Krejci629cdef2016-06-06 15:06:36 +02004116 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004117 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004118 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02004119 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02004120 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01004121 int f_mand = 0, c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004122 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004123
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004124 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01004125 if (!choice) {
4126 LOGMEM;
4127 return NULL;
4128 }
Radek Krejci76512572015-08-04 09:47:08 +02004129 choice->nodetype = LYS_CHOICE;
4130 choice->prev = (struct lys_node *)choice;
4131 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004132
Radek Krejci07d0fb92017-01-13 14:11:05 +01004133 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004134 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4135 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4136 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004137 goto error;
4138 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004139
Michal Vasko3e3228d2017-02-24 14:55:32 +01004140 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02004141
Michal Vasko3a0043f2015-08-12 12:11:30 +02004142 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004143 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004144 goto error;
4145 }
4146
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004147 /* process choice's specific children */
4148 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004149 if (strcmp(sub->ns->value, LY_NSYIN)) {
4150 /* extension */
4151 c_ext++;
4152 /* keep it for later processing, skip lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02004153 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004154 } else if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004155 if (!(node = read_yin_container(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004156 goto error;
4157 }
4158 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004159 if (!(node = read_yin_leaflist(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004160 goto error;
4161 }
4162 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004163 if (!(node = read_yin_leaf(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004164 goto error;
4165 }
4166 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004167 if (!(node = read_yin_list(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004168 goto error;
4169 }
4170 } else if (!strcmp(sub->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004171 if (!(node = read_yin_case(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004172 goto error;
4173 }
4174 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004175 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004176 goto error;
4177 }
4178 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004179 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004180 goto error;
4181 }
4182 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02004183 if (dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004184 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004185 goto error;
4186 }
Radek Krejci21c81652017-01-23 10:42:55 +01004187
Radek Krejci8d6b7422017-02-03 14:42:13 +01004188 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004189 goto error;
4190 }
4191
Radek Krejci629cdef2016-06-06 15:06:36 +02004192 dflt = sub;
4193 lyxml_unlink_elem(ctx, dflt, 0);
Radek Krejcif9a312c2016-06-06 15:14:30 +02004194 continue;
4195 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
4196
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004197 } else if (!strcmp(sub->name, "mandatory")) {
4198 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004199 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004200 goto error;
4201 }
4202 /* just checking the flags in leaf is not sufficient, we would allow
4203 * multiple mandatory statements with the "false" value
4204 */
4205 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004206
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004207 GETVAL(value, sub, "value");
4208 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004209 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004210 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004211 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004212 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004213 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004214 goto error;
4215 } /* else false is the default value, so we can ignore it */
Radek Krejci21c81652017-01-23 10:42:55 +01004216
Radek Krejci8d6b7422017-02-03 14:42:13 +01004217 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004218 goto error;
4219 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004220 } else if (!strcmp(sub->name, "when")) {
4221 if (choice->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004222 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004223 goto error;
4224 }
4225
Radek Krejci5323b492017-01-16 15:40:11 +01004226 choice->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004227 if (!choice->when) {
4228 goto error;
4229 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004230 } else if (!strcmp(sub->name, "if-feature")) {
4231 c_ftrs++;
4232
Michal Vasko345da0a2015-12-02 10:35:55 +01004233 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02004234 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02004235 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004236 if (!(node = read_yin_choice(module, retval, sub, options, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02004237 goto error;
4238 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004239 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004240 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004241 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004242 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004243
Radek Krejci1d82ef62015-08-07 14:44:40 +02004244 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01004245 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004246 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004247
Radek Krejci3cf9e222015-06-18 11:37:50 +02004248 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004249 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
4250 if (!choice->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004251 LOGMEM;
4252 goto error;
4253 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004254 }
Radek Krejcie534c132016-11-23 13:32:31 +01004255 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004256 /* some extensions may be already present from the substatements */
4257 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4258 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004259 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004260 goto error;
4261 }
Radek Krejci21c81652017-01-23 10:42:55 +01004262 retval->ext = reallocated;
4263
4264 /* init memory */
4265 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004266 }
4267
Radek Krejcie534c132016-11-23 13:32:31 +01004268 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4269 if (strcmp(sub->ns->value, LY_NSYIN)) {
4270 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004271 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 +01004272 retval->ext_size++;
4273 if (ret) {
4274 goto error;
4275 }
4276 } else {
4277 ret = fill_yin_iffeature(retval, 0, sub, &choice->iffeature[choice->iffeature_size], unres);
4278 choice->iffeature_size++;
4279 if (ret) {
4280 goto error;
4281 }
4282 }
4283 }
4284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004285 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02004286 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004287 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "default", "choice");
Michal Vasko51e5c582017-01-19 14:16:39 +01004288 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004289 goto error;
4290 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004291
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004292 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02004293 if (dflt) {
4294 GETVAL(value, dflt, "value");
4295 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004296 goto error;
4297 }
Radek Krejci629cdef2016-06-06 15:06:36 +02004298 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004299 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004300
Michal Vasko508a50d2016-09-07 14:50:33 +02004301 /* check XPath dependencies */
Radek Krejci7212e0a2017-03-08 15:58:22 +01004302 if (!(options & LYS_PARSE_OPT_INGRP) && choice->when &&
4303 (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02004304 goto error;
4305 }
4306
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004307 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004308
4309error:
4310
Radek Krejci629cdef2016-06-06 15:06:36 +02004311 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004312 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004313
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004314 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004315}
4316
Michal Vasko0d343d12015-08-24 14:57:36 +02004317/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004318static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004319read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004320 int options, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02004321{
Radek Krejci76512572015-08-04 09:47:08 +02004322 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02004323 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004324 struct lyxml_elem *sub, *next;
4325 const char *value;
4326 int r;
4327 int f_mand = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004328 int c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004329 void *reallocated;
Radek Krejci863c2852015-06-03 15:47:11 +02004330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004331 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01004332 if (!anyxml) {
4333 LOGMEM;
4334 return NULL;
4335 }
Radek Krejcibf2abff2016-08-23 15:51:52 +02004336 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02004337 anyxml->prev = (struct lys_node *)anyxml;
4338 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02004339
Radek Krejci07d0fb92017-01-13 14:11:05 +01004340 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004341 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4342 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4343 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004344 goto error;
4345 }
Radek Krejci863c2852015-06-03 15:47:11 +02004346
Michal Vasko3e3228d2017-02-24 14:55:32 +01004347 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004348
Radek Krejcic189a952016-07-11 15:27:07 +02004349 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004350 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004351 goto error;
4352 }
4353
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004354 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004355 if (strcmp(sub->ns->value, LY_NSYIN)) {
4356 /* extension */
4357 c_ext++;
4358 } else if (!strcmp(sub->name, "mandatory")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004359 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004360 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004361 goto error;
4362 }
4363 /* just checking the flags in leaf is not sufficient, we would allow
4364 * multiple mandatory statements with the "false" value
4365 */
4366 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02004367
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004368 GETVAL(value, sub, "value");
4369 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004370 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004371 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004372 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004373 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004374 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004375 goto error;
4376 }
4377 /* else false is the default value, so we can ignore it */
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004378
Radek Krejci8d6b7422017-02-03 14:42:13 +01004379 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004380 goto error;
4381 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004382 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004383 } else if (!strcmp(sub->name, "when")) {
4384 if (anyxml->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004385 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004386 goto error;
4387 }
4388
Radek Krejci5323b492017-01-16 15:40:11 +01004389 anyxml->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004390 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004391 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004392 goto error;
4393 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004394 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004395 } else if (!strcmp(sub->name, "must")) {
4396 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004397 } else if (!strcmp(sub->name, "if-feature")) {
4398 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02004399
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004400 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004401 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004402 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004403 }
4404 }
Radek Krejci863c2852015-06-03 15:47:11 +02004405
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004406 /* middle part - process nodes with cardinality of 0..n */
4407 if (c_must) {
4408 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004409 if (!anyxml->must) {
4410 LOGMEM;
4411 goto error;
4412 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004413 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004414 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004415 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
4416 if (!anyxml->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004417 LOGMEM;
4418 goto error;
4419 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004420 }
Radek Krejcie534c132016-11-23 13:32:31 +01004421 if (c_ext) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004422 /* some extensions may be already present from the substatements */
4423 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4424 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004425 LOGMEM;
4426 goto error;
4427 }
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004428 retval->ext = reallocated;
4429
4430 /* init memory */
4431 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004432 }
Radek Krejci863c2852015-06-03 15:47:11 +02004433
Radek Krejcie534c132016-11-23 13:32:31 +01004434 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4435 if (strcmp(sub->ns->value, LY_NSYIN)) {
4436 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004437 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 +01004438 retval->ext_size++;
4439 if (r) {
4440 goto error;
4441 }
4442 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004443 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004444 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004445 if (r) {
4446 goto error;
4447 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004448 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004449 r = fill_yin_iffeature(retval, 0, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004450 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004451 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004452 goto error;
4453 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004454 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004455 }
Radek Krejci863c2852015-06-03 15:47:11 +02004456
Michal Vasko508a50d2016-09-07 14:50:33 +02004457 /* check XPath dependencies */
Radek Krejci7212e0a2017-03-08 15:58:22 +01004458 if (!(options & LYS_PARSE_OPT_INGRP) && (anyxml->when || anyxml->must_size) &&
4459 (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02004460 goto error;
4461 }
4462
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004463 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02004464
4465error:
4466
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004467 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02004468
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004469 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02004470}
4471
Michal Vasko0d343d12015-08-24 14:57:36 +02004472/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004473static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004474read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004475 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004476{
Radek Krejci76512572015-08-04 09:47:08 +02004477 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004478 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004479 struct lyxml_elem *sub, *next;
4480 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01004481 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004482 int c_must = 0, c_ftrs = 0, f_mand = 0, c_ext = 0;
Radek Krejcifccd1442017-01-16 10:26:57 +01004483 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004484
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004485 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01004486 if (!leaf) {
4487 LOGMEM;
4488 return NULL;
4489 }
Radek Krejci76512572015-08-04 09:47:08 +02004490 leaf->nodetype = LYS_LEAF;
4491 leaf->prev = (struct lys_node *)leaf;
4492 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004493
Radek Krejci07d0fb92017-01-13 14:11:05 +01004494 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004495 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4496 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4497 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004498 goto error;
4499 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004500
Michal Vasko3e3228d2017-02-24 14:55:32 +01004501 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004502
Radek Krejcic189a952016-07-11 15:27:07 +02004503 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004504 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004505 goto error;
4506 }
4507
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004508 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004509 if (strcmp(sub->ns->value, LY_NSYIN)) {
4510 /* extension */
4511 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004512 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004513 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004514 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004515 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004516 goto error;
4517 }
Michal Vasko88c29542015-11-27 14:57:53 +01004518 /* HACK for unres */
4519 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004520 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004521 /* postpone type resolution when if-feature parsing is done since we need
4522 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004523 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004524 } else if (!strcmp(sub->name, "default")) {
4525 if (leaf->dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004526 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004527 goto error;
4528 }
4529 GETVAL(value, sub, "value");
4530 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci1abcdae2017-01-18 14:14:18 +01004531
Radek Krejci8d6b7422017-02-03 14:42:13 +01004532 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci1abcdae2017-01-18 14:14:18 +01004533 goto error;
4534 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004535 } else if (!strcmp(sub->name, "units")) {
4536 if (leaf->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004537 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004538 goto error;
4539 }
4540 GETVAL(value, sub, "name");
4541 leaf->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004542
Radek Krejci8d6b7422017-02-03 14:42:13 +01004543 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004544 goto error;
4545 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004546 } else if (!strcmp(sub->name, "mandatory")) {
4547 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004548 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004549 goto error;
4550 }
4551 /* just checking the flags in leaf is not sufficient, we would allow
4552 * multiple mandatory statements with the "false" value
4553 */
4554 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02004555
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004556 GETVAL(value, sub, "value");
4557 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004558 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004559 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004560 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004561 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004562 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004563 goto error;
4564 } /* else false is the default value, so we can ignore it */
Radek Krejcifccd1442017-01-16 10:26:57 +01004565
Radek Krejci8d6b7422017-02-03 14:42:13 +01004566 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004567 goto error;
4568 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004569 } else if (!strcmp(sub->name, "when")) {
4570 if (leaf->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004571 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004572 goto error;
4573 }
4574
Radek Krejci5323b492017-01-16 15:40:11 +01004575 leaf->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004576 if (!leaf->when) {
4577 goto error;
4578 }
4579
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004580 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02004581 c_must++;
4582 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004583 } else if (!strcmp(sub->name, "if-feature")) {
4584 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004585 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004586
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004587 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004588 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004589 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004590 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004591
Michal Vasko88c29542015-11-27 14:57:53 +01004592 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004593 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004594
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004595 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004596 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004597 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004598 goto error;
4599 }
Michal Vasko478c4652016-07-21 12:55:01 +02004600 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004601 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "mandatory", "leaf");
Michal Vasko51e5c582017-01-19 14:16:39 +01004602 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL,
Michal Vasko478c4652016-07-21 12:55:01 +02004603 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
4604 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004605 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004606
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004607 /* middle part - process nodes with cardinality of 0..n */
4608 if (c_must) {
4609 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004610 if (!leaf->must) {
4611 LOGMEM;
4612 goto error;
4613 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004614 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004615 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004616 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
4617 if (!leaf->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004618 LOGMEM;
4619 goto error;
4620 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004621 }
Radek Krejcie534c132016-11-23 13:32:31 +01004622 if (c_ext) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004623 /* some extensions may be already present from the substatements */
4624 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4625 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004626 LOGMEM;
4627 goto error;
4628 }
Radek Krejcifccd1442017-01-16 10:26:57 +01004629 retval->ext = reallocated;
4630
4631 /* init memory */
4632 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004633 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004634
Radek Krejcie534c132016-11-23 13:32:31 +01004635 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4636 if (strcmp(sub->ns->value, LY_NSYIN)) {
4637 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004638 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 +01004639 retval->ext_size++;
4640 if (r) {
4641 goto error;
4642 }
4643 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004644 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004645 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004646 if (r) {
4647 goto error;
4648 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004649 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004650 r = fill_yin_iffeature(retval, 0, sub, &leaf->iffeature[leaf->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004651 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004652 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004653 goto error;
4654 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004655 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004656 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004657
Radek Krejcicbb473e2016-09-16 14:48:32 +02004658 /* finalize type parsing */
4659 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
4660 leaf->type.der = NULL;
4661 goto error;
4662 }
4663
4664 /* check default value (if not defined, there still could be some restrictions
4665 * that need to be checked against a default value from a derived type) */
Radek Krejciab08f0f2017-03-09 16:37:15 +01004666 if (!(options & LYS_PARSE_OPT_INGRP) &&
4667 (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT,
4668 (struct lys_node *)(&leaf->dflt)) == -1)) {
Radek Krejcicbb473e2016-09-16 14:48:32 +02004669 goto error;
4670 }
4671
Michal Vasko508a50d2016-09-07 14:50:33 +02004672 /* check XPath dependencies */
Radek Krejci7212e0a2017-03-08 15:58:22 +01004673 if (!(options & LYS_PARSE_OPT_INGRP) && (leaf->when || leaf->must_size) &&
4674 (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02004675 goto error;
4676 }
4677
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004678 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004679
4680error:
4681
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004682 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004683
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004684 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004685}
4686
Michal Vasko0d343d12015-08-24 14:57:36 +02004687/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004688static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004689read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004690 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004691{
Radek Krejci76512572015-08-04 09:47:08 +02004692 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004693 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004694 struct lyxml_elem *sub, *next;
4695 const char *value;
4696 char *endptr;
4697 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004698 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004699 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004700 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejci5323b492017-01-16 15:40:11 +01004701 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004702
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004703 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01004704 if (!llist) {
4705 LOGMEM;
4706 return NULL;
4707 }
Radek Krejci76512572015-08-04 09:47:08 +02004708 llist->nodetype = LYS_LEAFLIST;
4709 llist->prev = (struct lys_node *)llist;
4710 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004711
Radek Krejci07d0fb92017-01-13 14:11:05 +01004712 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004713 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4714 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4715 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004716 goto error;
4717 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004718
Michal Vasko3e3228d2017-02-24 14:55:32 +01004719 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004720
Radek Krejcic189a952016-07-11 15:27:07 +02004721 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004722 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004723 goto error;
4724 }
4725
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004726 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004727 if (strcmp(sub->ns->value, LY_NSYIN)) {
4728 /* extension */
4729 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004730 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004731 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004732 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004733 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004734 goto error;
4735 }
Michal Vasko88c29542015-11-27 14:57:53 +01004736 /* HACK for unres */
4737 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004738 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004739 /* postpone type resolution when if-feature parsing is done since we need
4740 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004741 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004742 } else if (!strcmp(sub->name, "units")) {
4743 if (llist->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004744 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004745 goto error;
4746 }
4747 GETVAL(value, sub, "name");
4748 llist->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004749
Radek Krejci8d6b7422017-02-03 14:42:13 +01004750 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004751 goto error;
4752 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004753 } else if (!strcmp(sub->name, "ordered-by")) {
4754 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004755 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004756 goto error;
4757 }
4758 /* just checking the flags in llist is not sufficient, we would
4759 * allow multiple ordered-by statements with the "system" value
4760 */
4761 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004762
Radek Krejci1574a8d2015-08-03 14:16:52 +02004763 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004764 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4765 * state data
4766 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004767 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004768 continue;
4769 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004770
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004771 GETVAL(value, sub, "value");
4772 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004773 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004774 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004775 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004776 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02004777 } /* else system is the default value, so we can ignore it */
4778
Radek Krejci8d6b7422017-02-03 14:42:13 +01004779 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004780 goto error;
4781 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004782 } else if (!strcmp(sub->name, "must")) {
4783 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02004784 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004785 } else if (!strcmp(sub->name, "if-feature")) {
4786 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004787 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02004788 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004789 /* read the default's extension instances */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004790 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 +01004791 goto error;
4792 }
4793
Radek Krejcid5a5c282016-08-15 15:38:08 +02004794 c_dflt++;
4795 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004796
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004797 } else if (!strcmp(sub->name, "min-elements")) {
4798 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004799 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004800 goto error;
4801 }
4802 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004803
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004804 GETVAL(value, sub, "value");
4805 while (isspace(value[0])) {
4806 value++;
4807 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004808
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004809 /* convert it to uint32_t */
4810 errno = 0;
4811 endptr = NULL;
4812 val = strtoul(value, &endptr, 10);
4813 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004814 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004815 goto error;
4816 }
4817 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004818 if (llist->max && (llist->min > llist->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004819 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004820 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004821 goto error;
4822 }
Radek Krejci5323b492017-01-16 15:40:11 +01004823
Radek Krejci8d6b7422017-02-03 14:42:13 +01004824 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004825 goto error;
4826 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004827 } else if (!strcmp(sub->name, "max-elements")) {
4828 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004829 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004830 goto error;
4831 }
4832 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004833
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004834 GETVAL(value, sub, "value");
4835 while (isspace(value[0])) {
4836 value++;
4837 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004838
Radek Krejci0d7b2472016-02-12 11:11:03 +01004839 if (!strcmp(value, "unbounded")) {
4840 llist->max = 0;
4841 } else {
4842 /* convert it to uint32_t */
4843 errno = 0;
4844 endptr = NULL;
4845 val = strtoul(value, &endptr, 10);
4846 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004847 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004848 goto error;
4849 }
4850 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004851 if (llist->min > llist->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004852 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004853 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004854 goto error;
4855 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004856 }
Radek Krejci5323b492017-01-16 15:40:11 +01004857
Radek Krejci8d6b7422017-02-03 14:42:13 +01004858 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004859 goto error;
4860 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004861 } else if (!strcmp(sub->name, "when")) {
4862 if (llist->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004863 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004864 goto error;
4865 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004866
Radek Krejci5323b492017-01-16 15:40:11 +01004867 llist->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004868 if (!llist->when) {
4869 goto error;
4870 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004871 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004872 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004873 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004874 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004875
Michal Vasko88c29542015-11-27 14:57:53 +01004876 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004877 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004878
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004879 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004880 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004881 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004882 goto error;
4883 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004884
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004885 /* middle part - process nodes with cardinality of 0..n */
4886 if (c_must) {
4887 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004888 if (!llist->must) {
4889 LOGMEM;
4890 goto error;
4891 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004892 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004893 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004894 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
4895 if (!llist->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004896 LOGMEM;
4897 goto error;
4898 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004899 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004900 if (c_dflt) {
4901 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
4902 if (!llist->dflt) {
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004903 LOGMEM;
4904 goto error;
4905 }
4906 }
Radek Krejcie534c132016-11-23 13:32:31 +01004907 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01004908 /* some extensions may be already present from the substatements */
4909 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4910 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004911 LOGMEM;
4912 goto error;
4913 }
Radek Krejci5323b492017-01-16 15:40:11 +01004914 retval->ext = reallocated;
4915
4916 /* init memory */
4917 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004918 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004919
Radek Krejcie534c132016-11-23 13:32:31 +01004920 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4921 if (strcmp(sub->ns->value, LY_NSYIN)) {
4922 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004923 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 +01004924 retval->ext_size++;
4925 if (r) {
4926 goto error;
4927 }
4928 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004929 r = fill_yin_must(module, sub, &llist->must[llist->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004930 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004931 if (r) {
4932 goto error;
4933 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004934 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004935 r = fill_yin_iffeature(retval, 0, sub, &llist->iffeature[llist->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004936 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004937 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004938 goto error;
4939 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004940 } else if (!strcmp(sub->name, "default")) {
4941 GETVAL(value, sub, "value");
4942
Radek Krejciac1a52c2016-09-15 14:42:40 +02004943 /* check for duplicity in case of configuration data,
4944 * in case of status data duplicities are allowed */
4945 if (llist->flags & LYS_CONFIG_W) {
4946 for (r = 0; r < llist->dflt_size; r++) {
4947 if (ly_strequal(llist->dflt[r], value, 1)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004948 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, "default");
Michal Vasko51e5c582017-01-19 14:16:39 +01004949 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "Duplicated default value \"%s\".", value);
Radek Krejciac1a52c2016-09-15 14:42:40 +02004950 goto error;
4951 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004952 }
4953 }
4954 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004955 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004956 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004957
Radek Krejcicbb473e2016-09-16 14:48:32 +02004958 /* finalize type parsing */
4959 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
4960 llist->type.der = NULL;
4961 goto error;
4962 }
4963
Radek Krejcid5a5c282016-08-15 15:38:08 +02004964 if (llist->dflt_size && llist->min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004965 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "min-elements", "leaf-list");
Michal Vasko51e5c582017-01-19 14:16:39 +01004966 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02004967 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
4968 goto error;
4969 }
4970
4971 /* check default value (if not defined, there still could be some restrictions
4972 * that need to be checked against a default value from a derived type) */
4973 for (r = 0; r < llist->dflt_size; r++) {
Radek Krejciab08f0f2017-03-09 16:37:15 +01004974 if (!(options & LYS_PARSE_OPT_INGRP) &&
4975 (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
4976 (struct lys_node *)(&llist->dflt[r])) == -1)) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02004977 goto error;
Radek Krejci25d782a2015-05-22 15:03:23 +02004978 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004979 }
4980
Michal Vasko508a50d2016-09-07 14:50:33 +02004981 /* check XPath dependencies */
Radek Krejci7212e0a2017-03-08 15:58:22 +01004982 if (!(options & LYS_PARSE_OPT_INGRP) && (llist->when || llist->must_size) &&
4983 (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02004984 goto error;
4985 }
4986
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004987 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004988
4989error:
4990
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004991 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004992
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004993 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004994}
4995
Michal Vasko0d343d12015-08-24 14:57:36 +02004996/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004997static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004998read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004999 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005000{
Radek Krejci1d82ef62015-08-07 14:44:40 +02005001 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02005002 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005003 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01005004 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005005 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005006 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejci5c08a992016-11-02 13:30:04 +01005007 const char *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005008 char *auxs;
5009 unsigned long val;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005010 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005011
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005012 /* init */
5013 memset(&root, 0, sizeof root);
5014 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02005015
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005016 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01005017 if (!list) {
5018 LOGMEM;
5019 return NULL;
5020 }
Radek Krejci76512572015-08-04 09:47:08 +02005021 list->nodetype = LYS_LIST;
5022 list->prev = (struct lys_node *)list;
5023 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005024
Radek Krejci07d0fb92017-01-13 14:11:05 +01005025 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005026 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
5027 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
5028 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005029 goto error;
5030 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005031
Michal Vasko3e3228d2017-02-24 14:55:32 +01005032 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005033
Radek Krejcic189a952016-07-11 15:27:07 +02005034 /* insert the node into the schema tree */
5035 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5036 goto error;
5037 }
5038
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005039 /* process list's specific children */
5040 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005041 if (strcmp(sub->ns->value, LY_NSYIN)) {
5042 /* extension */
5043 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005044 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02005045
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005046 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005047 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005048 !strcmp(sub->name, "leaf-list") ||
5049 !strcmp(sub->name, "leaf") ||
5050 !strcmp(sub->name, "list") ||
5051 !strcmp(sub->name, "choice") ||
5052 !strcmp(sub->name, "uses") ||
5053 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005054 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005055 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005056 !strcmp(sub->name, "action") ||
5057 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005058 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005059 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005060
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005061 /* array counters */
5062 } else if (!strcmp(sub->name, "key")) {
5063 /* check cardinality 0..1 */
5064 if (list->keys_size) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005065 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005066 goto error;
5067 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005068
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005069 /* count the number of keys */
5070 GETVAL(value, sub, "value");
Radek Krejci5c08a992016-11-02 13:30:04 +01005071 list->keys_str = lydict_insert(module->ctx, value, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005072 while ((value = strpbrk(value, " \t\n"))) {
5073 list->keys_size++;
5074 while (isspace(*value)) {
5075 value++;
5076 }
5077 }
5078 list->keys_size++;
5079 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01005080 if (!list->keys) {
5081 LOGMEM;
5082 goto error;
5083 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005084
Radek Krejci8d6b7422017-02-03 14:42:13 +01005085 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_KEY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005086 goto error;
5087 }
5088 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005089 } else if (!strcmp(sub->name, "unique")) {
5090 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005091 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005092 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005093 } else if (!strcmp(sub->name, "typedef")) {
5094 c_tpdf++;
5095 } else if (!strcmp(sub->name, "must")) {
5096 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005097 } else if (!strcmp(sub->name, "if-feature")) {
5098 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02005099
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005100 /* optional stetments */
5101 } else if (!strcmp(sub->name, "ordered-by")) {
5102 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005103 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005104 goto error;
5105 }
5106 /* just checking the flags in llist is not sufficient, we would
5107 * allow multiple ordered-by statements with the "system" value
5108 */
5109 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005110
Radek Krejci1574a8d2015-08-03 14:16:52 +02005111 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005112 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
5113 * state data
5114 */
Michal Vasko345da0a2015-12-02 10:35:55 +01005115 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005116 continue;
5117 }
Radek Krejci345ad742015-06-03 11:04:18 +02005118
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005119 GETVAL(value, sub, "value");
5120 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02005121 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005122 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005123 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005124 goto error;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005125 } /* else system is the default value, so we can ignore it */
5126
Radek Krejci8d6b7422017-02-03 14:42:13 +01005127 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005128 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005129 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005130 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005131 } else if (!strcmp(sub->name, "min-elements")) {
5132 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005133 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005134 goto error;
5135 }
5136 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005137
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005138 GETVAL(value, sub, "value");
5139 while (isspace(value[0])) {
5140 value++;
5141 }
Radek Krejci345ad742015-06-03 11:04:18 +02005142
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005143 /* convert it to uint32_t */
5144 errno = 0;
5145 auxs = NULL;
5146 val = strtoul(value, &auxs, 10);
5147 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005148 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005149 goto error;
5150 }
5151 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005152 if (list->max && (list->min > list->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005153 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01005154 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005155 lyxml_free(module->ctx, sub);
5156 goto error;
5157 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005158 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005159 goto error;
5160 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005161 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005162 } else if (!strcmp(sub->name, "max-elements")) {
5163 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005164 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005165 goto error;
5166 }
5167 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005168
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005169 GETVAL(value, sub, "value");
5170 while (isspace(value[0])) {
5171 value++;
5172 }
Radek Krejci345ad742015-06-03 11:04:18 +02005173
Radek Krejci0d7b2472016-02-12 11:11:03 +01005174 if (!strcmp(value, "unbounded")) {
5175 list->max = 0;;
5176 } else {
5177 /* convert it to uint32_t */
5178 errno = 0;
5179 auxs = NULL;
5180 val = strtoul(value, &auxs, 10);
5181 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005182 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01005183 goto error;
5184 }
5185 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005186 if (list->min > list->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005187 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01005188 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005189 goto error;
5190 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005191 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005192 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005193 goto error;
5194 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005195 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005196 } else if (!strcmp(sub->name, "when")) {
5197 if (list->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005198 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005199 goto error;
5200 }
5201
Radek Krejci5323b492017-01-16 15:40:11 +01005202 list->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005203 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005204 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005205 goto error;
5206 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005207 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005208 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005209 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005210 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005211 }
5212 }
Radek Krejci345ad742015-06-03 11:04:18 +02005213
Michal Vaskoe022a562016-09-27 14:24:15 +02005214 /* check - if list is configuration, key statement is mandatory
5215 * (but only if we are not in a grouping or augment, then the check is deferred) */
Radek Krejcif95b6292017-02-13 15:57:37 +01005216 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); node = node->parent);
Radek Krejci5c08a992016-11-02 13:30:04 +01005217 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys_str) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005218 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005219 goto error;
5220 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005221
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005222 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5223 if (c_tpdf) {
5224 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005225 if (!list->tpdf) {
5226 LOGMEM;
5227 goto error;
5228 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005229 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005230 if (c_must) {
5231 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01005232 if (!list->must) {
5233 LOGMEM;
5234 goto error;
5235 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005236 }
5237 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005238 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
5239 if (!list->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005240 LOGMEM;
5241 goto error;
5242 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005243 }
Radek Krejcie534c132016-11-23 13:32:31 +01005244 if (c_ext) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005245 /* some extensions may be already present from the substatements */
5246 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5247 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005248 LOGMEM;
5249 goto error;
5250 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005251 retval->ext = reallocated;
5252
5253 /* init memory */
5254 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005255 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005256
Radek Krejcie534c132016-11-23 13:32:31 +01005257 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5258 if (strcmp(sub->ns->value, LY_NSYIN)) {
5259 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005260 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 +01005261 retval->ext_size++;
5262 if (r) {
5263 goto error;
5264 }
5265 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005266 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
5267 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005268 if (r) {
5269 goto error;
5270 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005271 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005272 r = fill_yin_iffeature(retval, 0, sub, &list->iffeature[list->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005273 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005274 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005275 goto error;
5276 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005277 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005278 r = fill_yin_must(module, sub, &list->must[list->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005279 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005280 if (r) {
5281 goto error;
5282 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005283 }
5284 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005286 /* last part - process data nodes */
5287 LY_TREE_FOR_SAFE(root.child, next, sub) {
5288 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005289 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005290 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005291 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005292 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005293 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005294 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005295 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005296 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005297 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005298 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005299 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005300 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005301 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005302 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005303 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005304 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005305 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005306 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005307 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005308 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005309 node = read_yin_notif(module, retval, sub, options, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005310 } else {
5311 LOGINT;
5312 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005313 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005314 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005315 goto error;
5316 }
Radek Krejci73adb602015-07-02 18:07:40 +02005317
Michal Vasko345da0a2015-12-02 10:35:55 +01005318 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005319 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005320
Radek Krejci5c08a992016-11-02 13:30:04 +01005321 if (list->keys_str) {
5322 /* check that we are not in grouping */
5323 for (node = parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
5324 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01005325 goto error;
5326 }
5327 } /* 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 +02005328
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005329 /* process unique statements */
5330 if (c_uniq) {
5331 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01005332 if (!list->unique) {
5333 LOGMEM;
5334 goto error;
5335 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005336
Radek Krejci461efb92016-02-12 15:52:18 +01005337 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
5338 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
5339 list->unique_size++;
5340 if (r) {
5341 goto error;
5342 }
5343
Radek Krejci8d6b7422017-02-03 14:42:13 +01005344 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub,
Radek Krejcie36d7c72017-01-17 16:12:30 +01005345 LYEXT_SUBSTMT_UNIQUE, list->unique_size - 1, unres)) {
5346 goto error;
5347 }
Radek Krejci461efb92016-02-12 15:52:18 +01005348 lyxml_free(module->ctx, sub);
5349 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005350 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005351
Michal Vasko508a50d2016-09-07 14:50:33 +02005352 /* check XPath dependencies */
Radek Krejci7212e0a2017-03-08 15:58:22 +01005353 if (!(options & LYS_PARSE_OPT_INGRP) && (list->when || list->must_size) &&
5354 (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02005355 goto error;
5356 }
5357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005358 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005359
5360error:
5361
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005362 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005363 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005364 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005365 }
5366 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005367 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005368 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005369
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005370 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005371}
5372
Michal Vasko0d343d12015-08-24 14:57:36 +02005373/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005374static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005375read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005376 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005377{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005378 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005379 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005380 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005381 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005382 const char *value;
Radek Krejci07d0fb92017-01-13 14:11:05 +01005383 void *reallocated;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005384 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005385 int c_tpdf = 0, c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005386
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005387 /* init */
5388 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005389
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005390 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01005391 if (!cont) {
5392 LOGMEM;
5393 return NULL;
5394 }
Radek Krejci76512572015-08-04 09:47:08 +02005395 cont->nodetype = LYS_CONTAINER;
5396 cont->prev = (struct lys_node *)cont;
5397 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005398
Radek Krejci07d0fb92017-01-13 14:11:05 +01005399 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005400 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
5401 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
5402 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005403 goto error;
5404 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005405
Michal Vasko3e3228d2017-02-24 14:55:32 +01005406 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005407
Radek Krejcic189a952016-07-11 15:27:07 +02005408 /* insert the node into the schema tree */
5409 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5410 goto error;
5411 }
5412
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005413 /* process container's specific children */
5414 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005415 if (strcmp(sub->ns->value, LY_NSYIN)) {
5416 /* extension */
5417 c_ext++;
5418 } else if (!strcmp(sub->name, "presence")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005419 if (cont->presence) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005420 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005421 goto error;
5422 }
5423 GETVAL(value, sub, "value");
5424 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02005425
Radek Krejci8d6b7422017-02-03 14:42:13 +01005426 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005427 goto error;
5428 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005429 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005430 } else if (!strcmp(sub->name, "when")) {
5431 if (cont->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005432 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005433 goto error;
5434 }
5435
Radek Krejci5323b492017-01-16 15:40:11 +01005436 cont->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005437 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005438 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005439 goto error;
5440 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005441 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02005442
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005443 /* data statements */
5444 } else if (!strcmp(sub->name, "container") ||
5445 !strcmp(sub->name, "leaf-list") ||
5446 !strcmp(sub->name, "leaf") ||
5447 !strcmp(sub->name, "list") ||
5448 !strcmp(sub->name, "choice") ||
5449 !strcmp(sub->name, "uses") ||
5450 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005451 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005452 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005453 !strcmp(sub->name, "action") ||
5454 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005455 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005456 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005457
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005458 /* array counters */
5459 } else if (!strcmp(sub->name, "typedef")) {
5460 c_tpdf++;
5461 } else if (!strcmp(sub->name, "must")) {
5462 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005463 } else if (!strcmp(sub->name, "if-feature")) {
5464 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005465 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005466 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005467 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005468 }
5469 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005470
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005471 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5472 if (c_tpdf) {
5473 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005474 if (!cont->tpdf) {
5475 LOGMEM;
5476 goto error;
5477 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005478 }
5479 if (c_must) {
5480 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01005481 if (!cont->must) {
5482 LOGMEM;
5483 goto error;
5484 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005485 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005486 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005487 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
5488 if (!cont->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005489 LOGMEM;
5490 goto error;
5491 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005492 }
Radek Krejcie534c132016-11-23 13:32:31 +01005493 if (c_ext) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01005494 /* some extensions may be already present from the substatements */
5495 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5496 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005497 LOGMEM;
5498 goto error;
5499 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01005500 retval->ext = reallocated;
5501
5502 /* init memory */
5503 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005504 }
Radek Krejci800af702015-06-02 13:46:01 +02005505
Radek Krejcie534c132016-11-23 13:32:31 +01005506 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5507 if (strcmp(sub->ns->value, LY_NSYIN)) {
5508 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005509 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 +01005510 retval->ext_size++;
5511 if (r) {
5512 goto error;
5513 }
5514 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005515 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
5516 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005517 if (r) {
5518 goto error;
5519 }
5520 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005521 r = fill_yin_must(module, sub, &cont->must[cont->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005522 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005523 if (r) {
5524 goto error;
5525 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005526 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005527 r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005528 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005529 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005530 goto error;
5531 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005532 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005533 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005534
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005535 /* last part - process data nodes */
5536 LY_TREE_FOR_SAFE(root.child, next, sub) {
5537 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005538 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005539 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005540 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005541 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005542 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005543 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005544 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005545 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005546 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005547 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005548 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005549 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005550 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005551 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005552 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005553 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005554 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005555 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005556 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005557 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005558 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005559 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005560 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005561 goto error;
5562 }
Radek Krejci73adb602015-07-02 18:07:40 +02005563
Michal Vasko345da0a2015-12-02 10:35:55 +01005564 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005565 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005566
Michal Vasko508a50d2016-09-07 14:50:33 +02005567 /* check XPath dependencies */
Radek Krejci7212e0a2017-03-08 15:58:22 +01005568 if (!(options & LYS_PARSE_OPT_INGRP) && (cont->when || cont->must_size) &&
5569 (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02005570 goto error;
5571 }
5572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005573 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005574
5575error:
5576
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005577 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005578 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005579 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005580 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005581
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005582 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005583}
5584
Michal Vasko0d343d12015-08-24 14:57:36 +02005585/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005586static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005587read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005588 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005589{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005590 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005591 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005592 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005593 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005594 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005595 int c_tpdf = 0, c_ext = 0;
Radek Krejcifdc0d702017-01-23 15:58:38 +01005596 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005597
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005598 /* init */
5599 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005600
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005601 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01005602 if (!grp) {
5603 LOGMEM;
5604 return NULL;
5605 }
Radek Krejci76512572015-08-04 09:47:08 +02005606 grp->nodetype = LYS_GROUPING;
5607 grp->prev = (struct lys_node *)grp;
5608 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005609
Radek Krejci07d0fb92017-01-13 14:11:05 +01005610 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE , unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005611 goto error;
5612 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005613
Michal Vasko3e3228d2017-02-24 14:55:32 +01005614 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005615
Radek Krejcic189a952016-07-11 15:27:07 +02005616 /* insert the node into the schema tree */
5617 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5618 goto error;
5619 }
5620
Radek Krejci1d82ef62015-08-07 14:44:40 +02005621 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005622 if (strcmp(sub->ns->value, LY_NSYIN)) {
5623 /* extension */
5624 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005625
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005626 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005627 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005628 !strcmp(sub->name, "leaf-list") ||
5629 !strcmp(sub->name, "leaf") ||
5630 !strcmp(sub->name, "list") ||
5631 !strcmp(sub->name, "choice") ||
5632 !strcmp(sub->name, "uses") ||
5633 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005634 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005635 !strcmp(sub->name, "anydata") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02005636 !strcmp(sub->name, "action") ||
5637 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005638 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005639 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005640
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005641 /* array counters */
5642 } else if (!strcmp(sub->name, "typedef")) {
5643 c_tpdf++;
5644 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005645 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005646 goto error;
5647 }
5648 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005649
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005650 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5651 if (c_tpdf) {
5652 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005653 if (!grp->tpdf) {
5654 LOGMEM;
5655 goto error;
5656 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005657 }
Radek Krejcie534c132016-11-23 13:32:31 +01005658 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01005659 /* some extensions may be already present from the substatements */
5660 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5661 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005662 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02005663 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005664 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01005665 retval->ext = reallocated;
5666
5667 /* init memory */
5668 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005669 }
Radek Krejcie534c132016-11-23 13:32:31 +01005670 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5671 if (strcmp(sub->ns->value, LY_NSYIN)) {
5672 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005673 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 +01005674 retval->ext_size++;
5675 if (r) {
5676 goto error;
5677 }
5678 } else {
5679 /* typedef */
5680 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
5681 grp->tpdf_size++;
5682 if (r) {
5683 goto error;
5684 }
5685 }
5686 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005687
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005688 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02005689 if (!root.child) {
5690 LOGWRN("Grouping \"%s\" without children.", retval->name);
5691 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01005692 options |= LYS_PARSE_OPT_INGRP;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005693 LY_TREE_FOR_SAFE(root.child, next, sub) {
5694 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005695 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005696 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005697 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005698 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005699 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005700 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005701 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005702 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005703 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005704 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005705 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005706 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005707 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005708 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005709 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005710 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005711 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005712 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005713 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02005714 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005715 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005716 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005717 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005718 goto error;
5719 }
Radek Krejci73adb602015-07-02 18:07:40 +02005720
Michal Vasko345da0a2015-12-02 10:35:55 +01005721 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005722 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005723
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005724 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005725
5726error:
5727
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005728 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005729 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005730 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005731 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005732
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005733 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005734}
5735
Michal Vasko0d343d12015-08-24 14:57:36 +02005736/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005737static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005738read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005739 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005740{
Radek Krejcie0674f82015-06-15 13:58:51 +02005741 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005742 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02005743 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02005744 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005745 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005746 int c_tpdf = 0, c_must = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005747
Radek Krejcie0674f82015-06-15 13:58:51 +02005748 /* init */
5749 memset(&root, 0, sizeof root);
5750
Michal Vasko38d01f72015-06-15 09:41:06 +02005751 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01005752 if (!inout) {
5753 LOGMEM;
5754 return NULL;
5755 }
Radek Krejci6acc8012015-08-13 09:07:04 +02005756 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005757
5758 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02005759 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005760 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005761 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02005762 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005763 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005764 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02005765 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02005766 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02005767 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005768 }
5769
Radek Krejci76512572015-08-04 09:47:08 +02005770 retval = (struct lys_node *)inout;
Radek Krejcie7770892017-01-24 13:18:01 +01005771 retval->module = module;
Michal Vaskoebeac942015-06-15 12:11:50 +02005772
Michal Vasko3e3228d2017-02-24 14:55:32 +01005773 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005774
Radek Krejcic189a952016-07-11 15:27:07 +02005775 /* insert the node into the schema tree */
5776 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5777 goto error;
5778 }
5779
Michal Vasko38d01f72015-06-15 09:41:06 +02005780 /* data statements */
5781 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie7770892017-01-24 13:18:01 +01005782 if (!sub->ns) {
5783 /* garbage */
5784 lyxml_free(module->ctx, sub);
5785 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01005786 /* extension */
5787 c_ext++;
5788 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005789 !strcmp(sub->name, "leaf-list") ||
5790 !strcmp(sub->name, "leaf") ||
5791 !strcmp(sub->name, "list") ||
5792 !strcmp(sub->name, "choice") ||
5793 !strcmp(sub->name, "uses") ||
5794 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005795 !strcmp(sub->name, "anyxml") ||
5796 !strcmp(sub->name, "anydata")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005797 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005798 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005799
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005800 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005801 } else if (!strcmp(sub->name, "typedef")) {
5802 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02005803
Radek Krejci1a31efe2016-07-29 11:04:16 +02005804 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005805 c_must++;
5806
Michal Vasko38d01f72015-06-15 09:41:06 +02005807 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005808 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005809 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005810 }
5811 }
5812
5813 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5814 if (c_tpdf) {
5815 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005816 if (!inout->tpdf) {
5817 LOGMEM;
5818 goto error;
5819 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005820 }
Radek Krejci19332802016-07-29 10:39:46 +02005821 if (c_must) {
5822 inout->must = calloc(c_must, sizeof *inout->must);
5823 if (!inout->must) {
5824 LOGMEM;
5825 goto error;
5826 }
5827 }
Radek Krejcie534c132016-11-23 13:32:31 +01005828 if (c_ext) {
5829 inout->ext = calloc(c_ext, sizeof *inout->ext);
5830 if (!inout->ext) {
5831 LOGMEM;
5832 goto error;
5833 }
5834 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005835
Radek Krejcie534c132016-11-23 13:32:31 +01005836 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5837 if (strcmp(sub->ns->value, LY_NSYIN)) {
5838 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005839 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 +01005840 retval->ext_size++;
5841 if (r) {
5842 goto error;
5843 }
5844 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005845 r = fill_yin_must(module, sub, &inout->must[inout->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02005846 inout->must_size++;
5847 if (r) {
5848 goto error;
5849 }
5850 } else { /* typedef */
5851 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
5852 inout->tpdf_size++;
5853 if (r) {
5854 goto error;
5855 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005856 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005857 }
5858
5859 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01005860 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko38d01f72015-06-15 09:41:06 +02005861 LY_TREE_FOR_SAFE(root.child, next, sub) {
5862 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005863 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005864 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005865 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005866 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005867 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005868 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005869 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005870 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005871 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005872 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005873 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005874 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005875 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005876 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005877 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005878 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005879 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005880 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005881 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005882 goto error;
5883 }
Radek Krejci73adb602015-07-02 18:07:40 +02005884
Michal Vasko345da0a2015-12-02 10:35:55 +01005885 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005886 }
5887
Michal Vasko508a50d2016-09-07 14:50:33 +02005888 /* check XPath dependencies */
Radek Krejci7212e0a2017-03-08 15:58:22 +01005889 if (!(options & LYS_PARSE_OPT_INGRP) && inout->must_size &&
5890 (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02005891 goto error;
5892 }
5893
Michal Vasko38d01f72015-06-15 09:41:06 +02005894 return retval;
5895
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005896error:
Michal Vasko38d01f72015-06-15 09:41:06 +02005897
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005898 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02005899 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005900 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005901 }
5902
5903 return NULL;
5904}
5905
Michal Vasko0d343d12015-08-24 14:57:36 +02005906/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005907static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005908read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005909 int options, struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02005910{
Michal Vaskoc6551b32015-06-16 10:51:43 +02005911 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005912 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005913 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005914 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005915 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005916 int c_tpdf = 0, c_ftrs = 0, c_must = 0, c_ext = 0;
Radek Krejci478ef1d2017-01-24 13:56:09 +01005917 void *reallocated;
Michal Vasko0ea41032015-06-16 08:53:55 +02005918
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005919 if (parent && (module->version < 2)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005920 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "notification");
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005921 return NULL;
5922 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005923
Michal Vaskoc6551b32015-06-16 10:51:43 +02005924 memset(&root, 0, sizeof root);
5925
Michal Vasko0ea41032015-06-16 08:53:55 +02005926 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01005927 if (!notif) {
5928 LOGMEM;
5929 return NULL;
5930 }
Radek Krejci76512572015-08-04 09:47:08 +02005931 notif->nodetype = LYS_NOTIF;
5932 notif->prev = (struct lys_node *)notif;
5933 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005934
Radek Krejci07d0fb92017-01-13 14:11:05 +01005935 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005936 goto error;
5937 }
5938
Michal Vasko3e3228d2017-02-24 14:55:32 +01005939 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005940
Radek Krejcic189a952016-07-11 15:27:07 +02005941 /* insert the node into the schema tree */
5942 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5943 goto error;
5944 }
5945
Michal Vasko0ea41032015-06-16 08:53:55 +02005946 /* process rpc's specific children */
5947 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005948 if (strcmp(sub->ns->value, LY_NSYIN)) {
5949 /* extension */
5950 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005951 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02005952
Michal Vasko0ea41032015-06-16 08:53:55 +02005953 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005954 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005955 !strcmp(sub->name, "leaf-list") ||
5956 !strcmp(sub->name, "leaf") ||
5957 !strcmp(sub->name, "list") ||
5958 !strcmp(sub->name, "choice") ||
5959 !strcmp(sub->name, "uses") ||
5960 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005961 !strcmp(sub->name, "anyxml") ||
5962 !strcmp(sub->name, "anydata")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005963 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005964 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02005965
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005966 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02005967 } else if (!strcmp(sub->name, "typedef")) {
5968 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005969 } else if (!strcmp(sub->name, "if-feature")) {
5970 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02005971 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005972 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02005973 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005974 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02005975 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02005976 }
5977 }
5978
5979 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5980 if (c_tpdf) {
5981 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005982 if (!notif->tpdf) {
5983 LOGMEM;
5984 goto error;
5985 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005986 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005987 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005988 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
5989 if (!notif->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005990 LOGMEM;
5991 goto error;
5992 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005993 }
Radek Krejci19332802016-07-29 10:39:46 +02005994 if (c_must) {
5995 notif->must = calloc(c_must, sizeof *notif->must);
5996 if (!notif->must) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005997 LOGMEM;
5998 goto error;
5999 }
6000 }
Radek Krejcie534c132016-11-23 13:32:31 +01006001 if (c_ext) {
Radek Krejci478ef1d2017-01-24 13:56:09 +01006002 /* some extensions may be already present from the substatements */
6003 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
6004 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01006005 LOGMEM;
6006 goto error;
6007 }
Radek Krejci478ef1d2017-01-24 13:56:09 +01006008 retval->ext = reallocated;
6009
6010 /* init memory */
6011 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006012 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006013
Radek Krejcie534c132016-11-23 13:32:31 +01006014 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6015 if (strcmp(sub->ns->value, LY_NSYIN)) {
6016 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006017 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 +01006018 retval->ext_size++;
6019 if (r) {
6020 goto error;
6021 }
6022 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006023 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
6024 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02006025 if (r) {
6026 goto error;
6027 }
Radek Krejci96299152016-06-22 10:17:50 +02006028 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006029 r = fill_yin_iffeature(retval, 0, sub, &notif->iffeature[notif->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006030 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006031 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006032 goto error;
6033 }
Radek Krejci19332802016-07-29 10:39:46 +02006034 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01006035 r = fill_yin_must(module, sub, &notif->must[notif->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02006036 notif->must_size++;
Radek Krejci0b24d752015-07-02 15:02:27 +02006037 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006038 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006039 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006040 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006041 }
6042
6043 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01006044 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko0ea41032015-06-16 08:53:55 +02006045 LY_TREE_FOR_SAFE(root.child, next, sub) {
6046 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006047 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006048 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006049 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006050 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006051 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006052 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006053 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006054 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006055 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006056 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006057 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006058 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006059 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006060 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006061 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02006062 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006063 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006064 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006065 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02006066 goto error;
6067 }
Radek Krejci73adb602015-07-02 18:07:40 +02006068
Michal Vasko345da0a2015-12-02 10:35:55 +01006069 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02006070 }
6071
Michal Vasko508a50d2016-09-07 14:50:33 +02006072 /* check XPath dependencies */
Radek Krejci7212e0a2017-03-08 15:58:22 +01006073 if (!(options & LYS_PARSE_OPT_INGRP) && notif->must_size &&
6074 (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02006075 goto error;
6076 }
6077
Michal Vasko0ea41032015-06-16 08:53:55 +02006078 return retval;
6079
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006080error:
Michal Vasko0ea41032015-06-16 08:53:55 +02006081
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006082 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02006083 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006084 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02006085 }
6086
6087 return NULL;
6088}
6089
Michal Vasko0d343d12015-08-24 14:57:36 +02006090/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02006091static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02006092read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01006093 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02006094{
Radek Krejcie0674f82015-06-15 13:58:51 +02006095 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006096 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02006097 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02006098 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006099 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01006100 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0, c_ext = 0;
Radek Krejci94596cf2017-01-24 13:19:16 +01006101 void *reallocated;
Michal Vasko38d01f72015-06-15 09:41:06 +02006102
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006103 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006104 if (module->version < 2) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006105 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "action");
Michal Vaskobb174852016-07-25 11:00:21 +02006106 return NULL;
6107 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006108 for (node = parent; node; node = lys_parent(node)) {
Radek Krejcia3b19f72016-09-30 13:02:45 +02006109 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006110 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006111 LOGVAL(LYE_INPAR, LY_VLOG_LYS, parent, strnodetype(node->nodetype), "action");
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006112 return NULL;
6113 }
6114 }
6115 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006116
Radek Krejcie0674f82015-06-15 13:58:51 +02006117 /* init */
6118 memset(&root, 0, sizeof root);
6119
Michal Vasko38d01f72015-06-15 09:41:06 +02006120 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01006121 if (!rpc) {
6122 LOGMEM;
6123 return NULL;
6124 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006125 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02006126 rpc->prev = (struct lys_node *)rpc;
6127 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006128
Radek Krejci07d0fb92017-01-13 14:11:05 +01006129 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006130 goto error;
6131 }
6132
Michal Vasko3e3228d2017-02-24 14:55:32 +01006133 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006134
Radek Krejcic189a952016-07-11 15:27:07 +02006135 /* insert the node into the schema tree */
6136 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6137 goto error;
6138 }
6139
Michal Vasko38d01f72015-06-15 09:41:06 +02006140 /* process rpc's specific children */
6141 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006142 if (strcmp(sub->ns->value, LY_NSYIN)) {
6143 /* extension */
6144 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006145 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006146 } else if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006147 if (c_input) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006148 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006149 goto error;
6150 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006151 c_input++;
Michal Vaskof3930de2015-10-22 12:03:59 +02006152 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006153 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006154 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006155 if (c_output) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006156 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006157 goto error;
6158 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006159 c_output++;
Michal Vaskof3930de2015-10-22 12:03:59 +02006160 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006161 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006162
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006163 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02006164 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02006165 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006166 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006167
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006168 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02006169 } else if (!strcmp(sub->name, "typedef")) {
6170 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006171 } else if (!strcmp(sub->name, "if-feature")) {
6172 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006173 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006174 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006175 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02006176 }
6177 }
6178
6179 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6180 if (c_tpdf) {
6181 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01006182 if (!rpc->tpdf) {
6183 LOGMEM;
6184 goto error;
6185 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006186 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006187 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006188 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
6189 if (!rpc->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01006190 LOGMEM;
6191 goto error;
6192 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006193 }
Radek Krejcie534c132016-11-23 13:32:31 +01006194 if (c_ext) {
Radek Krejci94596cf2017-01-24 13:19:16 +01006195 /* some extensions may be already present from the substatements */
6196 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
6197 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01006198 LOGMEM;
6199 goto error;
6200 }
Radek Krejci94596cf2017-01-24 13:19:16 +01006201 retval->ext = reallocated;
6202
6203 /* init memory */
6204 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006205 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006206
Radek Krejcie534c132016-11-23 13:32:31 +01006207 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6208 if (strcmp(sub->ns->value, LY_NSYIN)) {
6209 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006210 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 +01006211 retval->ext_size++;
6212 if (r) {
6213 goto error;
6214 }
6215 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006216 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
6217 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006218 if (r) {
6219 goto error;
6220 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006221 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006222 r = fill_yin_iffeature(retval, 0, sub, &rpc->iffeature[rpc->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006223 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006224 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006225 goto error;
6226 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006227 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006228 }
6229
6230 /* last part - process data nodes */
6231 LY_TREE_FOR_SAFE(root.child, next, sub) {
6232 if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006233 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006234 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006235 node = read_yin_input_output(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006236 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006237 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006238 goto error;
6239 }
Radek Krejci73adb602015-07-02 18:07:40 +02006240
Michal Vasko345da0a2015-12-02 10:35:55 +01006241 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006242 }
6243
Michal Vasko38d01f72015-06-15 09:41:06 +02006244 return retval;
6245
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006246error:
Michal Vasko38d01f72015-06-15 09:41:06 +02006247
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006248 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006249 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006250 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006251 }
6252
6253 return NULL;
6254}
6255
Michal Vasko0d343d12015-08-24 14:57:36 +02006256/* logs directly
6257 *
Radek Krejci74705112015-06-05 10:25:44 +02006258 * resolve - referenced grouping should be bounded to the namespace (resolved)
6259 * only when uses does not appear in grouping. In a case of grouping's uses,
6260 * we just get information but we do not apply augment or refine to it.
6261 */
Radek Krejci76512572015-08-04 09:47:08 +02006262static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01006263read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
6264 int options, struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02006265{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006266 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02006267 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006268 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006269 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01006270 int c_ref = 0, c_aug = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006271 int r;
Radek Krejcifdc0d702017-01-23 15:58:38 +01006272 void *reallocated;
Radek Krejci74705112015-06-05 10:25:44 +02006273
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006274 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01006275 if (!uses) {
6276 LOGMEM;
6277 return NULL;
6278 }
Radek Krejci76512572015-08-04 09:47:08 +02006279 uses->nodetype = LYS_USES;
6280 uses->prev = (struct lys_node *)uses;
6281 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02006282
Radek Krejcia9544502015-08-14 08:24:29 +02006283 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006284 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02006285
Radek Krejci07d0fb92017-01-13 14:11:05 +01006286 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006287 goto error;
6288 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006289
Michal Vasko3e3228d2017-02-24 14:55:32 +01006290 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006291
Radek Krejcic189a952016-07-11 15:27:07 +02006292 /* insert the node into the schema tree */
6293 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6294 goto error;
6295 }
6296
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006297 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02006298 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006299 if (strcmp(sub->ns->value, LY_NSYIN)) {
6300 /* extension */
6301 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006302 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006303 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006304 c_ref++;
6305 } else if (!strcmp(sub->name, "augment")) {
6306 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006307 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02006308 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006309 } else if (!strcmp(sub->name, "when")) {
6310 if (uses->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006311 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006312 goto error;
6313 }
6314
Radek Krejci5323b492017-01-16 15:40:11 +01006315 uses->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006316 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006317 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006318 goto error;
6319 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006320 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006321 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006322 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006323 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006324 }
6325 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006326
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006327 /* process properties with cardinality 0..n */
6328 if (c_ref) {
6329 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01006330 if (!uses->refine) {
6331 LOGMEM;
6332 goto error;
6333 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006334 }
6335 if (c_aug) {
6336 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01006337 if (!uses->augment) {
6338 LOGMEM;
6339 goto error;
6340 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006341 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006342 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006343 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
6344 if (!uses->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01006345 LOGMEM;
6346 goto error;
6347 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006348 }
Radek Krejcie534c132016-11-23 13:32:31 +01006349 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01006350 /* some extensions may be already present from the substatements */
6351 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
6352 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01006353 LOGMEM;
6354 goto error;
6355 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01006356 retval->ext = reallocated;
6357
6358 /* init memory */
6359 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006360 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006361
Radek Krejcie534c132016-11-23 13:32:31 +01006362 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6363 if (strcmp(sub->ns->value, LY_NSYIN)) {
6364 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006365 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 +01006366 retval->ext_size++;
6367 if (r) {
6368 goto error;
6369 }
6370 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02006371 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006372 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006373 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006374 goto error;
6375 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006376 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006377 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], options, unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006378 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006379 if (r) {
6380 goto error;
6381 }
6382 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006383 r = fill_yin_iffeature(retval, 0, sub, &uses->iffeature[uses->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006384 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006385 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006386 goto error;
6387 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006388 }
6389 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006390
Radek Krejci48464ed2016-03-17 15:44:09 +01006391 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006392 goto error;
6393 }
Radek Krejci74705112015-06-05 10:25:44 +02006394
Michal Vasko508a50d2016-09-07 14:50:33 +02006395 /* check XPath dependencies */
Radek Krejci7212e0a2017-03-08 15:58:22 +01006396 if (!(options & LYS_PARSE_OPT_INGRP) && uses->when &&
6397 (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02006398 goto error;
6399 }
6400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006401 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006402
6403error:
6404
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006405 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006406
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006407 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006408}
6409
Michal Vasko0d343d12015-08-24 14:57:36 +02006410/* logs directly
6411 *
6412 * common code for yin_read_module() and yin_read_submodule()
6413 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006414static int
Radek Krejcic071c542016-01-27 14:57:51 +01006415read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
6416 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02006417{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006418 struct ly_ctx *ctx = module->ctx;
Radek Krejci7417a082017-02-16 11:07:59 +01006419 struct lyxml_elem *next, *child, root, grps, augs, revs, exts;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006420 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006421 struct lys_module *trg;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006422 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01006423 int i, r, ret = -1;
Radek Krejcic071c542016-01-27 14:57:51 +01006424 int version_flag = 0;
Michal Vasko5de8a022017-02-08 10:57:26 +01006425 /* (sub)module substatements are ordered in groups, increment this value when moving to another group
6426 * 0 - header-stmts, 1 - linkage-stmts, 2 - meta-stmts, 3 - revision-stmts, 4 - body-stmts */
6427 int substmt_group;
6428 /* just remember last substatement for logging */
6429 const char *substmt_prev;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006430 /* counters */
Radek Krejcie534c132016-11-23 13:32:31 +01006431 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;
6432 int c_ext = 0, c_extinst = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01006433 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006434
Radek Krejcic071c542016-01-27 14:57:51 +01006435 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02006436 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01006437
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006438 /* init */
6439 memset(&root, 0, sizeof root);
6440 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006441 memset(&augs, 0, sizeof augs);
Radek Krejcie534c132016-11-23 13:32:31 +01006442 memset(&exts, 0, sizeof exts);
PavolVican9e81c6a2017-02-09 13:09:07 +01006443 memset(&revs, 0, sizeof revs);
Radek Krejcie0674f82015-06-15 13:58:51 +02006444
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006445 /*
6446 * in the first run, we process elements with cardinality of 1 or 0..1 and
6447 * count elements with cardinality 0..n. Data elements (choices, containers,
6448 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
6449 * need have all top-level and groupings already prepared at that time. In
6450 * the middle loop, we process other elements with carinality of 0..n since
6451 * we need to allocate arrays to store them.
6452 */
Michal Vasko5de8a022017-02-08 10:57:26 +01006453 substmt_group = 0;
6454 substmt_prev = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006455 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01006456 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02006457 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01006458 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006459 continue;
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006460 } else if (strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01006461 /* possible extension instance */
6462 lyxml_unlink_elem(module->ctx, child, 2);
6463 lyxml_add_child(module->ctx, &exts, child);
6464 c_extinst++;
6465 } else if (!submodule && !strcmp(child->name, "namespace")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006466 if (substmt_group > 0) {
6467 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6468 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6469 child->name, substmt_prev);
6470 goto error;
6471 }
6472
PavolVican9e81c6a2017-02-09 13:09:07 +01006473 if (trg->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006474 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006475 goto error;
6476 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006477 GETVAL(value, child, "uri");
PavolVican9e81c6a2017-02-09 13:09:07 +01006478 trg->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006479
Radek Krejci8d6b7422017-02-03 14:42:13 +01006480 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_NAMESPACE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006481 goto error;
6482 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006483 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006484
6485 substmt_prev = "namespace";
Radek Krejcic071c542016-01-27 14:57:51 +01006486 } else if (!submodule && !strcmp(child->name, "prefix")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006487 if (substmt_group > 0) {
6488 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6489 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6490 child->name, substmt_prev);
6491 goto error;
6492 }
6493
PavolVican9e81c6a2017-02-09 13:09:07 +01006494 if (trg->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006495 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006496 goto error;
6497 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006498 GETVAL(value, child, "value");
PavolVican9e81c6a2017-02-09 13:09:07 +01006499 if (lyp_check_identifier(value, LY_IDENT_PREFIX, trg, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006500 goto error;
6501 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006502 trg->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006503
Radek Krejci8d6b7422017-02-03 14:42:13 +01006504 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006505 goto error;
6506 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006507 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006508
6509 substmt_prev = "prefix";
Radek Krejcic071c542016-01-27 14:57:51 +01006510 } else if (submodule && !strcmp(child->name, "belongs-to")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006511 if (substmt_group > 0) {
6512 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6513 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6514 child->name, substmt_prev);
6515 goto error;
6516 }
6517
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006518 if (trg->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006519 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006520 goto error;
6521 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006522 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01006523 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006524 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006525 goto error;
6526 }
Radek Krejcif3886932015-06-04 17:36:06 +02006527
Radek Krejci8d6b7422017-02-03 14:42:13 +01006528 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_BELONGSTO, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006529 goto error;
6530 }
6531
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006532 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006533 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006534 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006535 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006536 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006537 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006538 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006539 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006540 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006541 goto error;
6542 }
6543 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006544 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006545 /* check here differs from a generic prefix check, since this prefix
6546 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02006547 */
Radek Krejci48464ed2016-03-17 15:44:09 +01006548 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006549 goto error;
6550 }
Radek Krejcic071c542016-01-27 14:57:51 +01006551 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02006552
Radek Krejci8d6b7422017-02-03 14:42:13 +01006553 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 +01006554 goto error;
6555 }
6556
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006557 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01006558 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02006559
Michal Vasko5de8a022017-02-08 10:57:26 +01006560 substmt_prev = "belongs-to";
6561
Radek Krejcieb00f512015-07-01 16:44:58 +02006562 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006563 } else if (!strcmp(child->name, "import")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006564 if (substmt_group > 1) {
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 substmt_group = 1;
6571
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006572 c_imp++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006573
6574 substmt_prev = "import";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006575 } else if (!strcmp(child->name, "revision")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006576 if (substmt_group > 3) {
6577 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6578 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6579 child->name, substmt_prev);
6580 goto error;
6581 }
6582 substmt_group = 3;
6583
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006584 c_rev++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006585
PavolVican9e81c6a2017-02-09 13:09:07 +01006586 lyxml_unlink_elem(ctx, child, 2);
6587 lyxml_add_child(ctx, &revs, child);
6588
Michal Vasko5de8a022017-02-08 10:57:26 +01006589 substmt_prev = "revision";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006590 } else if (!strcmp(child->name, "typedef")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006591 substmt_group = 4;
6592
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006593 c_tpdf++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006594
6595 substmt_prev = "typedef";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006596 } else if (!strcmp(child->name, "identity")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006597 substmt_group = 4;
6598
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006599 c_ident++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006600
6601 substmt_prev = "identity";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006602 } else if (!strcmp(child->name, "include")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006603 if (substmt_group > 1) {
6604 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6605 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6606 child->name, substmt_prev);
6607 goto error;
6608 }
6609 substmt_group = 1;
6610
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006611 c_inc++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006612
6613 substmt_prev = "include";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006614 } else if (!strcmp(child->name, "augment")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006615 substmt_group = 4;
6616
Radek Krejcif5be10f2015-06-16 13:29:36 +02006617 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006618 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01006619 lyxml_unlink_elem(ctx, child, 2);
6620 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006621
Michal Vasko5de8a022017-02-08 10:57:26 +01006622 substmt_prev = "augment";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006623 } else if (!strcmp(child->name, "feature")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006624 substmt_group = 4;
6625
Radek Krejci3cf9e222015-06-18 11:37:50 +02006626 c_ftrs++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006627
Michal Vasko5de8a022017-02-08 10:57:26 +01006628 substmt_prev = "feature";
Michal Vasko5de8a022017-02-08 10:57:26 +01006629
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006630 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006631 } else if (!strcmp(child->name, "container") ||
6632 !strcmp(child->name, "leaf-list") ||
6633 !strcmp(child->name, "leaf") ||
6634 !strcmp(child->name, "list") ||
6635 !strcmp(child->name, "choice") ||
6636 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006637 !strcmp(child->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01006638 !strcmp(child->name, "anydata") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006639 !strcmp(child->name, "rpc") ||
6640 !strcmp(child->name, "notification")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006641 substmt_group = 4;
6642
Radek Krejcic071c542016-01-27 14:57:51 +01006643 lyxml_unlink_elem(ctx, child, 2);
6644 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006645
Michal Vasko5de8a022017-02-08 10:57:26 +01006646 substmt_prev = "data definition";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006647 } else if (!strcmp(child->name, "grouping")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006648 substmt_group = 4;
6649
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006650 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01006651 lyxml_unlink_elem(ctx, child, 2);
6652 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006653
Michal Vasko5de8a022017-02-08 10:57:26 +01006654 substmt_prev = "grouping";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006655 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006656 } else if (!strcmp(child->name, "description")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006657 if (substmt_group > 2) {
6658 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6659 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6660 child->name, substmt_prev);
6661 goto error;
6662 }
6663 substmt_group = 2;
6664
Radek Krejcic071c542016-01-27 14:57:51 +01006665 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006666 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006667 goto error;
6668 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006669 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006670 goto error;
6671 }
Radek Krejcic071c542016-01-27 14:57:51 +01006672 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006673 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006674 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006675 goto error;
6676 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006677
6678 substmt_prev = "description";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006679 } else if (!strcmp(child->name, "reference")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006680 if (substmt_group > 2) {
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 = 2;
6687
Radek Krejcic071c542016-01-27 14:57:51 +01006688 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006689 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006690 goto error;
6691 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006692 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006693 goto error;
6694 }
Radek Krejcic071c542016-01-27 14:57:51 +01006695 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006696 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006697 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006698 goto error;
6699 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006700
6701 substmt_prev = "reference";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006702 } else if (!strcmp(child->name, "organization")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006703 if (substmt_group > 2) {
6704 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6705 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6706 child->name, substmt_prev);
6707 goto error;
6708 }
6709 substmt_group = 2;
6710
Radek Krejcic071c542016-01-27 14:57:51 +01006711 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006712 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006713 goto error;
6714 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006715 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_ORGANIZATION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006716 goto error;
6717 }
Radek Krejcic071c542016-01-27 14:57:51 +01006718 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006719 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006720 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006721 goto error;
6722 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006723
6724 substmt_prev = "organization";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006725 } else if (!strcmp(child->name, "contact")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006726 if (substmt_group > 2) {
6727 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6728 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6729 child->name, substmt_prev);
6730 goto error;
6731 }
6732 substmt_group = 2;
6733
Radek Krejcic071c542016-01-27 14:57:51 +01006734 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006735 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006736 goto error;
6737 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006738 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_CONTACT, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006739 goto error;
6740 }
Radek Krejcic071c542016-01-27 14:57:51 +01006741 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006742 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006743 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006744 goto error;
6745 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006746
6747 substmt_prev = "contact";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006748 } else if (!strcmp(child->name, "yang-version")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006749 if (substmt_group > 0) {
6750 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6751 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6752 child->name, substmt_prev);
6753 goto error;
6754 }
6755
Radek Krejcic071c542016-01-27 14:57:51 +01006756 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006757 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006758 goto error;
6759 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006760 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02006761 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006762 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006763 goto error;
6764 }
Radek Krejcic071c542016-01-27 14:57:51 +01006765 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006766 if (!strcmp(value, "1")) {
6767 if (submodule) {
6768 if (module->version > 1) {
6769 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6770 goto error;
6771 }
6772 } else {
6773 module->version = 1;
6774 }
6775 } else {
6776 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006777 if (module->version < 2) {
Michal Vasko88de3e42016-06-29 11:05:32 +02006778 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6779 goto error;
6780 }
6781 } else {
6782 module->version = 2;
6783 }
6784 }
6785
Radek Krejci8d6b7422017-02-03 14:42:13 +01006786 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_VERSION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006787 goto error;
6788 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006789 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006790
Michal Vasko5de8a022017-02-08 10:57:26 +01006791 substmt_prev = "yang-version";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006792 } else if (!strcmp(child->name, "extension")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006793 substmt_group = 4;
6794
Radek Krejcia1a6b762016-11-14 09:53:38 +09006795 c_ext++;
Radek Krejci5166a892015-07-02 16:44:24 +02006796
Michal Vasko5de8a022017-02-08 10:57:26 +01006797 substmt_prev = "extension";
Radek Krejcia1a6b762016-11-14 09:53:38 +09006798 } else if (!strcmp(child->name, "deviation")) {
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006799 substmt_group = 4;
6800
Radek Krejcia1a6b762016-11-14 09:53:38 +09006801 c_dev++;
6802
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006803 substmt_prev = "deviation";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006804 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01006805 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006806 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006807 }
6808 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006809
Radek Krejcic071c542016-01-27 14:57:51 +01006810 /* check for mandatory statements */
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006811 if (submodule) {
6812 if (!submodule->prefix) {
6813 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
6814 goto error;
6815 }
6816 if (!version_flag) {
6817 /* check version compatibility with the main module */
6818 if (module->version > 1) {
6819 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6820 goto error;
6821 }
6822 }
6823 } else {
PavolVican9e81c6a2017-02-09 13:09:07 +01006824 if (!trg->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006825 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006826 goto error;
6827 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006828 if (!trg->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006829 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006830 goto error;
6831 }
6832 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02006833
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006834 /* allocate arrays for elements with cardinality of 0..n */
6835 if (c_imp) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006836 trg->imp = calloc(c_imp, sizeof *trg->imp);
Radek Krejcic071c542016-01-27 14:57:51 +01006837 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01006838 LOGMEM;
6839 goto error;
6840 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006841 }
6842 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006843 trg->rev = calloc(c_rev, sizeof *trg->rev);
6844 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01006845 LOGMEM;
6846 goto error;
6847 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006848 }
6849 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01006850 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
6851 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01006852 LOGMEM;
6853 goto error;
6854 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006855 }
6856 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01006857 trg->ident = calloc(c_ident, sizeof *trg->ident);
6858 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01006859 LOGMEM;
6860 goto error;
6861 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006862 }
6863 if (c_inc) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006864 trg->inc = calloc(c_inc, sizeof *trg->inc);
Radek Krejcic071c542016-01-27 14:57:51 +01006865 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01006866 LOGMEM;
6867 goto error;
6868 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006869 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006870 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01006871 trg->augment = calloc(c_aug, sizeof *trg->augment);
6872 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01006873 LOGMEM;
6874 goto error;
6875 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006876 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006877 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01006878 trg->features = calloc(c_ftrs, sizeof *trg->features);
6879 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01006880 LOGMEM;
6881 goto error;
6882 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006883 }
Radek Krejcieb00f512015-07-01 16:44:58 +02006884 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006885 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
6886 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01006887 LOGMEM;
6888 goto error;
6889 }
Radek Krejcieb00f512015-07-01 16:44:58 +02006890 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09006891 if (c_ext) {
6892 trg->extensions = calloc(c_ext, sizeof *trg->extensions);
6893 if (!trg->extensions) {
6894 LOGMEM;
6895 goto error;
6896 }
6897 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006898
PavolVican9e81c6a2017-02-09 13:09:07 +01006899 /* middle part 1 - process revision and then check whether this (sub)module was not already parsed, add it there */
6900 LY_TREE_FOR_SAFE(revs.child, next, child) {
Radek Krejci7417a082017-02-16 11:07:59 +01006901 r = fill_yin_revision(trg, child, &trg->rev[trg->rev_size], unres);
6902 trg->rev_size++;
6903 if (r) {
PavolVican9e81c6a2017-02-09 13:09:07 +01006904 goto error;
6905 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006906
Radek Krejci7417a082017-02-16 11:07:59 +01006907 /* check uniqueness of the revision date - not required by RFC */
6908 for (i = 0; i < (trg->rev_size - 1); i++) {
6909 if (!strcmp(trg->rev[i].date, trg->rev[trg->rev_size - 1].date)) {
6910 LOGWRN("Module's revisions are not unique (%s).", trg->rev[trg->rev_size - 1].date);
6911 break;
PavolVican9e81c6a2017-02-09 13:09:07 +01006912 }
6913 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006914
6915 lyxml_free(ctx, child);
6916 }
6917
6918 /* check the module with respect to the context now */
6919 if (!submodule) {
6920 switch (lyp_ctx_check_module(module)) {
6921 case -1:
6922 goto error;
6923 case 0:
6924 break;
6925 case 1:
6926 /* it's already there */
6927 ret = 1;
6928 goto error;
6929 }
6930 }
6931
6932 /* middle part 2 - process nodes with cardinality of 0..n except the data nodes and augments */
Michal Vasko2f7925f2015-10-21 15:06:56 +02006933 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02006934 if (!strcmp(child->name, "import")) {
Radek Krejcie534c132016-11-23 13:32:31 +01006935 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size], unres);
Radek Krejcic071c542016-01-27 14:57:51 +01006936 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006937 if (r) {
6938 goto error;
6939 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006940
Radek Krejci1d82ef62015-08-07 14:44:40 +02006941 } else if (!strcmp(child->name, "include")) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006942 r = fill_yin_include(module, submodule, child, &trg->inc[trg->inc_size], unres);
6943 trg->inc_size++;
6944 if (r) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006945 goto error;
6946 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006947
Radek Krejci1d82ef62015-08-07 14:44:40 +02006948 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006949 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
6950 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006951 if (r) {
6952 goto error;
6953 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006954
Radek Krejci1d82ef62015-08-07 14:44:40 +02006955 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006956 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
6957 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006958 if (r) {
6959 goto error;
6960 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006961
Radek Krejci1d82ef62015-08-07 14:44:40 +02006962 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006963 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
6964 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006965 if (r) {
6966 goto error;
6967 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006968
Radek Krejcia1a6b762016-11-14 09:53:38 +09006969 } else if (!strcmp(child->name, "extension")) {
Radek Krejcie534c132016-11-23 13:32:31 +01006970 r = fill_yin_extension(trg, child, &trg->extensions[trg->extensions_size], unres);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006971 trg->extensions_size++;
6972 if (r) {
6973 goto error;
6974 }
6975
Radek Krejci1d82ef62015-08-07 14:44:40 +02006976 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006977 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
6978 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02006979 if (r) {
6980 goto error;
6981 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006982 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006983 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006984
Radek Krejcie534c132016-11-23 13:32:31 +01006985 /* process extension instances */
Radek Krejci8ee94802017-02-10 12:38:40 +01006986 if (c_extinst) {
6987 /* some extensions may be already present from the substatements */
6988 reallocated = realloc(trg->ext, (c_extinst + trg->ext_size) * sizeof *trg->ext);
6989 if (!reallocated) {
6990 LOGMEM;
Radek Krejcie534c132016-11-23 13:32:31 +01006991 goto error;
6992 }
Radek Krejci8ee94802017-02-10 12:38:40 +01006993 trg->ext = reallocated;
6994
6995 /* init memory */
6996 memset(&trg->ext[trg->ext_size], 0, c_extinst * sizeof *trg->ext);
6997
6998 LY_TREE_FOR_SAFE(exts.child, next, child) {
6999 r = lyp_yin_fill_ext(trg, LYEXT_PAR_MODULE, 0, 0, trg, child, &trg->ext, trg->ext_size, unres);
7000 trg->ext_size++;
7001 if (r) {
7002 goto error;
7003 }
7004 }
Radek Krejcie534c132016-11-23 13:32:31 +01007005 }
7006
Radek Krejcif5be10f2015-06-16 13:29:36 +02007007 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01007008 * refer to them. Submodule's data nodes are stored in the
7009 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007010 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02007011 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007012 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007013 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007014 goto error;
7015 }
Radek Krejci74705112015-06-05 10:25:44 +02007016
Michal Vasko345da0a2015-12-02 10:35:55 +01007017 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007018 }
Radek Krejci74705112015-06-05 10:25:44 +02007019
Radek Krejcif5be10f2015-06-16 13:29:36 +02007020 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02007021 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02007022
Radek Krejci1d82ef62015-08-07 14:44:40 +02007023 if (!strcmp(child->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007024 node = read_yin_container(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007025 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007026 node = read_yin_leaflist(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007027 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007028 node = read_yin_leaf(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007029 } else if (!strcmp(child->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007030 node = read_yin_list(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007031 } else if (!strcmp(child->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007032 node = read_yin_choice(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007033 } else if (!strcmp(child->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007034 node = read_yin_uses(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007035 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007036 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02007037 } else if (!strcmp(child->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007038 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007039 } else if (!strcmp(child->name, "rpc")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007040 node = read_yin_rpc_action(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007041 } else if (!strcmp(child->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007042 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007043 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02007044 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007045 goto error;
7046 }
Radek Krejci25d782a2015-05-22 15:03:23 +02007047
Michal Vasko345da0a2015-12-02 10:35:55 +01007048 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007049 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007050
Michal Vasko2f7925f2015-10-21 15:06:56 +02007051 /* ... and finally augments (last, so we can augment our data, for instance) */
7052 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007053 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], 0, unres);
Radek Krejcic071c542016-01-27 14:57:51 +01007054 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02007055
Michal Vasko2f7925f2015-10-21 15:06:56 +02007056 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02007057 goto error;
7058 }
Michal Vasko345da0a2015-12-02 10:35:55 +01007059 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02007060 }
7061
PavolVican9e81c6a2017-02-09 13:09:07 +01007062 return 0;
Radek Krejciefaeba32015-05-27 14:30:57 +02007063
7064error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007065 while (root.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007066 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007067 }
7068 while (grps.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007069 lyxml_free(ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007070 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007071 while (augs.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007072 lyxml_free(ctx, augs.child);
7073 }
7074 while (revs.child) {
7075 lyxml_free(ctx, revs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02007076 }
Radek Krejcie534c132016-11-23 13:32:31 +01007077 while (exts.child) {
7078 lyxml_free(module->ctx, exts.child);
7079 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007080
PavolVican9e81c6a2017-02-09 13:09:07 +01007081 return ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007082}
7083
Michal Vasko0d343d12015-08-24 14:57:36 +02007084/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007085struct lys_submodule *
7086yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02007087{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007088 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01007089 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007090 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02007091
Michal Vasko5a721fd2016-02-16 12:16:48 +01007092 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02007093
Radek Krejcie1bacd72017-03-01 13:18:46 +01007094 yin = lyxml_parse_mem(module->ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007095 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01007096 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007097 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007098
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007099 /* check root element */
7100 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01007101 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007102 goto error;
7103 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007104
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007105 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01007106 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007107 goto error;
7108 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007109
Michal Vasko5a721fd2016-02-16 12:16:48 +01007110 submodule = calloc(1, sizeof *submodule);
7111 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007112 LOGMEM;
7113 goto error;
7114 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007115
Michal Vasko5a721fd2016-02-16 12:16:48 +01007116 submodule->ctx = module->ctx;
7117 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
7118 submodule->type = 1;
7119 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02007120
Radek Krejci9e757e02017-03-08 17:18:09 +01007121 /* add into the list of processed modules */
7122 if (lyp_check_circmod_add((struct lys_module *)submodule)) {
7123 goto error;
7124 }
7125
Michal Vasko5a721fd2016-02-16 12:16:48 +01007126 LOGVRB("Reading submodule \"%s\".", submodule->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007127 /* module cannot be changed in this case and 1 cannot be returned */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007128 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007129 goto error;
7130 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007131
Radek Krejci33fc4772017-01-26 16:00:35 +01007132 lyp_sort_revisions((struct lys_module *)submodule);
7133
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007134 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01007135 lyxml_free(module->ctx, yin);
Radek Krejci9e757e02017-03-08 17:18:09 +01007136 lyp_check_circmod_pop(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02007137
Michal Vasko5a721fd2016-02-16 12:16:48 +01007138 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007139 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02007140
7141error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007142 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007143 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01007144 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01007145
Michal Vasko5a721fd2016-02-16 12:16:48 +01007146 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01007147 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01007148 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01007149 }
7150
Michal Vasko5a721fd2016-02-16 12:16:48 +01007151 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01007152
Radek Krejci9e757e02017-03-08 17:18:09 +01007153 lyp_check_circmod_pop(module->ctx);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007154 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
7155 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007156 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007157 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02007158}
7159
Michal Vasko0d343d12015-08-24 14:57:36 +02007160/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02007161struct lys_module *
Radek Krejci37f9ba32017-02-10 16:50:35 +01007162yin_read_module_(struct ly_ctx *ctx, struct lyxml_elem *yin, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02007163{
Pavol Vicanc99b59e2016-03-22 15:46:39 +01007164 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01007165 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007166 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01007167 int ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007168
Radek Krejcic071c542016-01-27 14:57:51 +01007169 unres = calloc(1, sizeof *unres);
7170 if (!unres) {
7171 LOGMEM;
7172 return NULL;
7173 }
7174
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007175 /* check root element */
7176 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci9a909bd2016-10-24 15:45:51 +02007177 if (ly_strequal("submodule", yin->name, 0)) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007178 LOGVAL(LYE_SUBMODULE, LY_VLOG_NONE, NULL);
7179 } else {
7180 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci9a909bd2016-10-24 15:45:51 +02007181 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007182 goto error;
7183 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007184
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007185 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01007186 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007187 goto error;
7188 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007189
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007190 module = calloc(1, sizeof *module);
7191 if (!module) {
7192 LOGMEM;
7193 goto error;
7194 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007195
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007196 module->ctx = ctx;
7197 module->name = lydict_insert(ctx, value, strlen(value));
7198 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02007199 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02007200
Radek Krejci9e757e02017-03-08 17:18:09 +01007201 /* add into the list of processed modules */
7202 if (lyp_check_circmod_add(module)) {
7203 goto error;
7204 }
7205
Michal Vasko9f258e42016-02-11 11:36:27 +01007206 LOGVRB("Reading module \"%s\".", module->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007207 ret = read_sub_module(module, NULL, yin, unres);
7208 if (ret == -1) {
Radek Krejcic071c542016-01-27 14:57:51 +01007209 goto error;
7210 }
7211
PavolVican9e81c6a2017-02-09 13:09:07 +01007212 if (ret == 1) {
7213 assert(!unres->count);
7214 } else {
7215 /* resolve rest of unres items */
7216 if (unres->count && resolve_unres_schema(module, unres)) {
7217 goto error;
7218 }
7219
7220 /* check correctness of includes */
7221 if (lyp_check_include_missing(module)) {
7222 goto error;
7223 }
Michal Vasko7b460e52017-02-10 14:50:26 +01007224
7225 /* remove our submodules from the parsed submodules list */
7226 lyp_del_includedup(module);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007227 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007228
Radek Krejci95f22ae2017-01-20 14:25:53 +01007229 lyp_sort_revisions(module);
Radek Krejci6bd2c022017-02-01 15:04:49 +01007230
7231 if (lyp_rfn_apply_ext(module) || lyp_deviation_apply_ext(module)) {
7232 goto error;
7233 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01007234
Radek Krejciff4874d2016-03-07 12:30:50 +01007235 if (revision) {
7236 /* check revision of the parsed model */
7237 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01007238 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
7239 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01007240 goto error;
7241 }
7242 }
7243
PavolVican9e81c6a2017-02-09 13:09:07 +01007244 /* add into context if not already there */
7245 if (!ret) {
7246 if (module->deviation_size && !module->implemented) {
7247 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
7248 /* deviations always causes target to be made implemented,
7249 * but augents and leafrefs not, so we have to apply them now */
7250 if (lys_set_implemented(module)) {
7251 goto error;
7252 }
7253 }
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007254
PavolVican9e81c6a2017-02-09 13:09:07 +01007255 if (lyp_ctx_add_module(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02007256 goto error;
7257 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007258 } else {
7259 /* free what was parsed */
7260 lys_free(module, NULL, 0);
7261
7262 /* get the model from the context */
7263 module = (struct lys_module *)ly_ctx_get_module(ctx, value, revision);
7264 assert(module);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007265 }
7266
Radek Krejcic071c542016-01-27 14:57:51 +01007267 unres_schema_free(NULL, &unres);
Radek Krejci9e757e02017-03-08 17:18:09 +01007268 lyp_check_circmod_pop(ctx);
Michal Vasko9f258e42016-02-11 11:36:27 +01007269 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007270 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007271
7272error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007273 /* cleanup */
Radek Krejcib8c07b82016-02-12 11:11:55 +01007274 unres_schema_free(module, &unres);
7275
7276 if (!module) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007277 if (ly_vecode != LYVE_SUBMODULE) {
7278 LOGERR(ly_errno, "Module parsing failed.");
7279 }
Radek Krejcib8c07b82016-02-12 11:11:55 +01007280 return NULL;
7281 }
7282
7283 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02007284
Radek Krejci9e757e02017-03-08 17:18:09 +01007285 lyp_check_circmod_pop(ctx);
Michal Vaskocf0489e2017-02-13 11:57:45 +01007286 lyp_del_includedup(module);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007287 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01007288 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007289 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007290}
Radek Krejci8d6b7422017-02-03 14:42:13 +01007291
Radek Krejci37f9ba32017-02-10 16:50:35 +01007292/* logs directly */
7293struct lys_module *
7294yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
7295{
7296 struct lyxml_elem *yin;
7297 struct lys_module *result;
7298
Radek Krejcie1bacd72017-03-01 13:18:46 +01007299 yin = lyxml_parse_mem(ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci37f9ba32017-02-10 16:50:35 +01007300 if (!yin) {
7301 LOGERR(ly_errno, "Module parsing failed.");
7302 return NULL;
7303 }
7304
7305 result = yin_read_module_(ctx, yin, revision, implement);
7306
7307 lyxml_free(ctx, yin);
7308
7309 return result;
7310}
7311
Radek Krejcic1885952017-02-07 09:37:51 +01007312static int
7313yin_parse_extcomplex_bool(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007314 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007315 const char *true_val, const char *false_val, struct unres_schema *unres)
7316{
7317 uint8_t *val;
7318 const char *str;
7319 struct lyext_substmt *info;
7320
7321 val = lys_ext_complex_get_substmt(stmt, ext, &info);
7322 if (!val) {
7323 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7324 return EXIT_FAILURE;
7325 }
7326 if (*val) {
7327 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7328 return EXIT_FAILURE;
7329 }
7330
Radek Krejcidb35f172017-02-27 11:03:01 +01007331 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007332 return EXIT_FAILURE;
7333 }
7334
7335 str = lyxml_get_attr(node, "value", NULL);
7336 if (!str) {
7337 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
7338 } else if (true_val && !strcmp(true_val, str)) {
7339 /* true value */
7340 *val = 1;
7341 } else if (false_val && !strcmp(false_val, str)) {
7342 /* false value */
7343 *val = 2;
7344 } else {
7345 /* unknown value */
7346 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
7347 return EXIT_FAILURE;
7348 }
7349
7350 return EXIT_SUCCESS;
7351}
7352
Radek Krejci8d6b7422017-02-03 14:42:13 +01007353/*
7354 * argelem - 1 if the value is stored in a standalone YIN element, 0 if stored as attribute
7355 * argname - name of the element/attribute where the value is stored
7356 */
7357static int
7358yin_parse_extcomplex_str(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007359 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejci8d6b7422017-02-03 14:42:13 +01007360 int argelem, const char *argname, struct unres_schema *unres)
7361{
7362 int c;
PavolVican99c70722017-02-18 17:25:52 +01007363 const char **str, ***p = NULL, *value;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007364 void *reallocated;
7365 struct lyext_substmt *info;
7366
7367 str = lys_ext_complex_get_substmt(stmt, ext, &info);
7368 if (!str) {
7369 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7370 return EXIT_FAILURE;
7371 }
7372 if (info->cardinality < LY_STMT_CARD_SOME && *str) {
7373 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7374 return EXIT_FAILURE;
7375 }
7376
7377 c = 0;
7378 if (info->cardinality >= LY_STMT_CARD_SOME) {
7379 /* there can be multiple instances, str is actually const char *** */
7380 p = (const char ***)str;
Radek Krejci56c80412017-02-09 10:44:16 +01007381 if (!p[0]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007382 /* allocate initial array */
Radek Krejci56c80412017-02-09 10:44:16 +01007383 p[0] = malloc(2 * sizeof(const char *));
7384 if (stmt == LY_STMT_BELONGSTO) {
7385 /* allocate another array for the belongs-to's prefixes */
7386 p[1] = malloc(2 * sizeof(const char *));
PavolVican99c70722017-02-18 17:25:52 +01007387 } else if (stmt == LY_STMT_ARGUMENT) {
7388 /* allocate another array for the yin element */
PavolVican4b80d042017-02-23 14:30:27 +01007389 ((uint8_t **)p)[1] = malloc(2 * sizeof(uint8_t));
Radek Krejci56c80412017-02-09 10:44:16 +01007390 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007391 } else {
Radek Krejci56c80412017-02-09 10:44:16 +01007392 /* get the index in the array to add new item */
7393 for (c = 0; p[0][c]; c++);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007394 }
Radek Krejci56c80412017-02-09 10:44:16 +01007395 str = p[0];
Radek Krejci8d6b7422017-02-03 14:42:13 +01007396 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007397 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, c, unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007398 return EXIT_FAILURE;
7399 }
7400
7401 if (argelem) {
Radek Krejci56c80412017-02-09 10:44:16 +01007402 str[c] = read_yin_subnode(mod->ctx, node, argname);
7403 if (!str[c]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007404 return EXIT_FAILURE;
7405 }
Radek Krejci56c80412017-02-09 10:44:16 +01007406 } else {
7407 str[c] = lyxml_get_attr(node, argname, NULL);
7408 if (!str[c]) {
7409 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, argname, node->name);
7410 return EXIT_FAILURE;
7411 } else {
7412 str[c] = lydict_insert(mod->ctx, str[c], 0);
7413 }
7414
7415 if (stmt == LY_STMT_BELONGSTO) {
7416 /* get the belongs-to's mandatory prefix substatement */
7417 if (!node->child) {
7418 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", node->name);
7419 return EXIT_FAILURE;
7420 } else if (strcmp(node->child->name, "prefix")) {
7421 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
7422 return EXIT_FAILURE;
7423 } else if (node->child->next) {
7424 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
7425 return EXIT_FAILURE;
7426 }
7427 /* and now finally get the value */
7428 if (p) {
7429 str = p[1];
7430 } else {
7431 str++;
7432 }
7433 str[c] = lyxml_get_attr(node->child, "value", ((void *)0));
7434 if (!str[c]) {
7435 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
7436 return EXIT_FAILURE;
7437 }
7438 str[c] = lydict_insert(mod->ctx, str[c], 0);
7439
PavolVican6d400872017-03-01 15:19:18 +01007440 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 +01007441 return EXIT_FAILURE;
7442 }
PavolVican99c70722017-02-18 17:25:52 +01007443 } else if (stmt == LY_STMT_ARGUMENT) {
7444 str = (p) ? p[1] : str + 1;
7445 if (!node->child) {
7446 /* default value of yin element */
7447 ((uint8_t *)str)[c] = 2;
7448 } else {
7449 /* get optional yin-element substatement */
7450 if (strcmp(node->child->name, "yin-element")) {
7451 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
7452 return EXIT_FAILURE;
7453 } else if (node->child->next) {
7454 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
7455 return EXIT_FAILURE;
7456 } else {
7457 /* and now finally get the value */
7458 value = lyxml_get_attr(node->child, "value", NULL);
7459 if (!value) {
7460 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
7461 return EXIT_FAILURE;
7462 }
7463 if (ly_strequal(value, "true", 0)) {
7464 ((uint8_t *)str)[c] = 1;
7465 } else if (ly_strequal(value, "false", 0)) {
7466 ((uint8_t *)str)[c] = 2;
7467 } else {
7468 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
7469 return EXIT_FAILURE;
7470 }
7471
7472 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node->child, LYEXT_SUBSTMT_YINELEM, c, unres)) {
7473 return EXIT_FAILURE;
7474 }
7475 }
7476 }
Radek Krejci56c80412017-02-09 10:44:16 +01007477 }
7478 }
7479 if (p) {
7480 /* enlarge the array(s) */
7481 reallocated = realloc(p[0], (c + 2) * sizeof(const char *));
7482 if (!reallocated) {
7483 LOGMEM;
7484 lydict_remove(mod->ctx, p[0][c]);
7485 p[0][c] = NULL;
7486 return EXIT_FAILURE;
7487 }
7488 p[0] = reallocated;
7489 p[0][c + 1] = NULL;
7490
7491 if (stmt == LY_STMT_BELONGSTO) {
7492 /* enlarge the second belongs-to's array with prefixes */
7493 reallocated = realloc(p[1], (c + 2) * sizeof(const char *));
7494 if (!reallocated) {
7495 LOGMEM;
7496 lydict_remove(mod->ctx, p[1][c]);
7497 p[1][c] = NULL;
7498 return EXIT_FAILURE;
7499 }
7500 p[1] = reallocated;
7501 p[1][c + 1] = NULL;
PavolVican99c70722017-02-18 17:25:52 +01007502 } else if (stmt == LY_STMT_ARGUMENT){
7503 /* enlarge the second argument's array with yin element */
7504 reallocated = realloc(p[1], (c + 2) * sizeof(uint8_t));
7505 if (!reallocated) {
7506 LOGMEM;
7507 ((uint8_t *)p[1])[c] = 0;
7508 return EXIT_FAILURE;
7509 }
7510 p[1] = reallocated;
7511 ((uint8_t *)p[1])[c + 1] = 0;
Radek Krejci56c80412017-02-09 10:44:16 +01007512 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007513 }
7514
7515 return EXIT_SUCCESS;
7516}
7517
7518static void *
7519yin_getplace_for_extcomplex_flags(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt,
7520 uint16_t mask)
7521{
7522 void *data;
7523 struct lyext_substmt *info;
7524
7525 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7526 if (!data) {
7527 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7528 return NULL;
7529 }
7530 if (info->cardinality < LY_STMT_CARD_SOME && ((*(uint16_t *)data) & mask)) {
7531 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7532 return NULL;
7533 }
7534
7535 return data;
7536}
7537
Radek Krejcic1885952017-02-07 09:37:51 +01007538static int
7539yin_parse_extcomplex_flag(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007540 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007541 const char *val1_str, const char *val2_str, uint16_t mask,
7542 uint16_t val1, uint16_t val2, struct unres_schema *unres)
7543{
7544 uint16_t *val;
7545 const char *str;
7546
7547 val = yin_getplace_for_extcomplex_flags(node, ext, stmt, mask);
7548 if (!val) {
7549 return EXIT_FAILURE;
7550 }
7551
7552 str = lyxml_get_attr(node, "value", NULL);
7553 if (!str) {
7554 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
7555 } else if (!strcmp(val1_str, str)) {
7556 *val = *val | val1;
7557 } else if (!strcmp(val2_str, str)) {
7558 *val = *val | val2;
7559 } else {
7560 /* unknown value */
7561 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
7562 return EXIT_FAILURE;
7563 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007564 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007565 return EXIT_FAILURE;
7566 }
7567 return EXIT_SUCCESS;
7568}
7569
Radek Krejcif95b6292017-02-13 15:57:37 +01007570static struct lys_node **
7571yin_getplace_for_extcomplex_node(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7572{
7573 struct lyext_substmt *info;
7574 struct lys_node **snode, *siter;
7575
7576 snode = lys_ext_complex_get_substmt(stmt, ext, &info);
7577 if (!snode) {
7578 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7579 return NULL;
7580 }
7581 if (info->cardinality < LY_STMT_CARD_SOME) {
7582 LY_TREE_FOR(*snode, siter) {
7583 if (stmt == lys_snode2stmt(siter->nodetype)) {
7584 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7585 return NULL;
7586 }
7587 }
7588 }
7589
7590 return snode;
7591}
7592
Radek Krejci8d6b7422017-02-03 14:42:13 +01007593static void **
7594yin_getplace_for_extcomplex_struct(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7595{
7596 int c;
7597 void **data, ***p = NULL;
7598 void *reallocated;
7599 struct lyext_substmt *info;
7600
7601 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7602 if (!data) {
7603 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7604 return NULL;
7605 }
7606 if (info->cardinality < LY_STMT_CARD_SOME && *data) {
7607 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7608 return NULL;
7609 }
7610
7611 c = 0;
7612 if (info->cardinality >= LY_STMT_CARD_SOME) {
7613 /* there can be multiple instances, so instead of pointer to array,
7614 * we have in data pointer to pointer to array */
7615 p = (void ***)data;
7616 data = *p;
7617 if (!data) {
7618 /* allocate initial array */
7619 *p = data = malloc(2 * sizeof(void *));
7620 } else {
7621 for (c = 0; *data; data++, c++);
7622 }
7623 }
7624
7625 if (p) {
7626 /* enlarge the array */
7627 reallocated = realloc(*p, (c + 2) * sizeof(void *));
7628 if (!reallocated) {
7629 LOGMEM;
7630 return NULL;
7631 }
7632 *p = reallocated;
7633 data = *p;
7634 data[c + 1] = NULL;
7635 }
7636
7637 return &data[c];
7638}
7639
7640int
7641lyp_yin_parse_complex_ext(struct lys_module *mod, struct lys_ext_instance_complex *ext, struct lyxml_elem *yin,
7642 struct unres_schema *unres)
7643{
Radek Krejciaa9c5202017-02-15 16:10:14 +01007644 struct lyxml_elem *next, *node, *child;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007645 struct lys_type **type;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007646 void **pp, *p, *reallocated;
Radek Krejciaa9c5202017-02-15 16:10:14 +01007647 const char *value, *name;
7648 char *endptr, modifier;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007649 struct lyext_substmt *info;
7650 long int v;
Radek Krejci5496fae2017-02-10 13:26:48 +01007651 long long int ll;
7652 unsigned long u;
Radek Krejci7417a082017-02-16 11:07:59 +01007653 int i, j;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007654
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007655#define YIN_EXTCOMPLEX_GETPLACE(STMT, TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007656 p = lys_ext_complex_get_substmt(STMT, ext, &info); \
7657 if (!p) { \
7658 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
7659 goto error; \
7660 } \
7661 if (info->cardinality < LY_STMT_CARD_SOME && (*(TYPE*)p)) { \
7662 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
7663 goto error; \
7664 } \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007665 pp = NULL; i = 0; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007666 if (info->cardinality >= LY_STMT_CARD_SOME) { \
7667 /* there can be multiple instances */ \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007668 pp = p; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007669 if (!(*pp)) { \
7670 *pp = malloc(2 * sizeof(TYPE)); /* allocate initial array */ \
7671 } else { \
7672 for (i = 0; (*(TYPE**)pp)[i]; i++); \
7673 } \
7674 p = &(*(TYPE**)pp)[i]; \
7675 }
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007676#define YIN_EXTCOMPLEX_ENLARGE(TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007677 if (pp) { \
7678 /* enlarge the array */ \
7679 reallocated = realloc(*pp, (i + 2) * sizeof(TYPE*)); \
7680 if (!reallocated) { \
7681 LOGMEM; \
7682 goto error; \
7683 } \
7684 *pp = reallocated; \
7685 (*(TYPE**)pp)[i + 1] = 0; \
7686 }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007687#define YIN_EXTCOMPLEX_PARSE_SNODE(STMT, FUNC, ARGS...) \
7688 pp = (void**)yin_getplace_for_extcomplex_node(node, ext, STMT); \
7689 if (!pp) { goto error; } \
Radek Krejci7212e0a2017-03-08 15:58:22 +01007690 if (!FUNC(mod, (struct lys_node*)ext, node, ##ARGS, LYS_PARSE_OPT_CFG_NOINHERIT, unres)) { goto error; }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007691#define YIN_EXTCOMPLEX_PARSE_RESTR(STMT) \
7692 YIN_EXTCOMPLEX_GETPLACE(STMT, struct lys_restr*); \
7693 GETVAL(value, node, "value"); \
7694 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr)); \
7695 (*(struct lys_restr **)p)->expr = lydict_insert(mod->ctx, value, 0); \
7696 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) { \
7697 goto error; \
7698 } \
7699 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007700
Radek Krejci8d6b7422017-02-03 14:42:13 +01007701 LY_TREE_FOR_SAFE(yin->child, next, node) {
7702 if (!node->ns) {
7703 /* garbage */
7704 } else if (node->ns == yin->ns && (ext->flags & LYS_YINELEM) && ly_strequal(node->name, ext->def->argument, 1)) {
7705 /* we have the extension's argument */
7706 if (ext->arg_value) {
7707 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
7708 goto error;
7709 }
7710 ext->arg_value = node->content;
7711 node->content = NULL;
7712 } else if (strcmp(node->ns->value, LY_NSYIN)) {
7713 /* extension */
7714 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_SELF, 0, unres)) {
7715 goto error;
7716 }
7717 } else if (!strcmp(node->name, "description")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007718 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DESCRIPTION, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007719 goto error;
7720 }
7721 } else if (!strcmp(node->name, "reference")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007722 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REFERENCE, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007723 goto error;
7724 }
7725 } else if (!strcmp(node->name, "units")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007726 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_UNITS, 0, "name", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007727 goto error;
7728 }
7729 } else if (!strcmp(node->name, "type")) {
7730 type = (struct lys_type **)yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPE);
7731 if (!type) {
7732 goto error;
7733 }
7734 /* allocate type structure */
7735 (*type) = calloc(1, sizeof **type);
7736
7737 /* HACK for unres */
Radek Krejci63fc0962017-02-15 13:20:18 +01007738 lyxml_unlink(mod->ctx, node);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007739 (*type)->der = (struct lys_tpdf *)node;
7740 (*type)->parent = (struct lys_tpdf *)ext;
7741
7742 if (unres_schema_add_node(mod, unres, *type, UNRES_TYPE_DER_EXT, NULL) == -1) {
7743 (*type)->der = NULL;
7744 goto error;
7745 }
7746 continue; /* skip lyxml_free() */
Radek Krejci63fc0962017-02-15 13:20:18 +01007747 } else if (!strcmp(node->name, "typedef")) {
7748 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPEDEF);
7749 if (!pp) {
7750 goto error;
7751 }
7752 /* allocate typedef structure */
7753 (*pp) = calloc(1, sizeof(struct lys_tpdf));
7754
7755 if (fill_yin_typedef(mod, (struct lys_node *)ext, node, *((struct lys_tpdf **)pp), unres)) {
7756 goto error;
7757 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007758 } else if (!strcmp(node->name, "if-feature")) {
7759 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_IFFEATURE);
7760 if (!pp) {
7761 goto error;
7762 }
7763 /* allocate iffeature structure */
7764 (*pp) = calloc(1, sizeof(struct lys_iffeature));
7765
7766 if (fill_yin_iffeature((struct lys_node *)ext, 0, node, *((struct lys_iffeature **)pp), unres)) {
7767 goto error;
7768 }
7769 } else if (!strcmp(node->name, "status")) {
7770 p = yin_getplace_for_extcomplex_flags(node, ext, LY_STMT_STATUS, LYS_STATUS_MASK);
7771 if (!p) {
7772 goto error;
7773 }
7774
7775 GETVAL(value, node, "value");
7776 if (!strcmp(value, "current")) {
7777 *(uint16_t*)p |= LYS_STATUS_CURR;
7778 } else if (!strcmp(value, "deprecated")) {
7779 *(uint16_t*)p |= LYS_STATUS_DEPRC;
7780 } else if (!strcmp(value, "obsolete")) {
7781 *(uint16_t*)p |= LYS_STATUS_OBSLT;
7782 } else {
7783 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
7784 goto error;
7785 }
7786
7787 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, 0, unres)) {
7788 goto error;
7789 }
Radek Krejcic1885952017-02-07 09:37:51 +01007790 } else if (!strcmp(node->name, "config")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007791 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY, "true", "false", LYS_CONFIG_MASK,
Radek Krejcic1885952017-02-07 09:37:51 +01007792 LYS_CONFIG_W | LYS_CONFIG_SET, LYS_CONFIG_R | LYS_CONFIG_SET, unres)) {
7793 goto error;
7794 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007795 } else if (!strcmp(node->name, "argument")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007796 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ARGUMENT, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007797 goto error;
7798 }
7799 } else if (!strcmp(node->name, "default")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007800 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DEFAULT, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007801 goto error;
7802 }
Radek Krejcic1885952017-02-07 09:37:51 +01007803 } else if (!strcmp(node->name, "mandatory")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007804 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY,
Radek Krejcic1885952017-02-07 09:37:51 +01007805 "true", "false", LYS_MAND_MASK, LYS_MAND_TRUE, LYS_MAND_FALSE, unres)) {
7806 goto error;
7807 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007808 } else if (!strcmp(node->name, "error-app-tag")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007809 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRTAG, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007810 goto error;
7811 }
7812 } else if (!strcmp(node->name, "error-message")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007813 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRMSG, 1, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007814 goto error;
7815 }
7816 } else if (!strcmp(node->name, "prefix")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007817 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PREFIX, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007818 goto error;
7819 }
7820 } else if (!strcmp(node->name, "namespace")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007821 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_NAMESPACE, 0, "uri", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007822 goto error;
7823 }
7824 } else if (!strcmp(node->name, "presence")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007825 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PRESENCE, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007826 goto error;
7827 }
7828 } else if (!strcmp(node->name, "revision-date")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007829 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REVISIONDATE, 0, "date", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007830 goto error;
7831 }
7832 } else if (!strcmp(node->name, "key")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007833 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_KEY, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007834 goto error;
7835 }
7836 } else if (!strcmp(node->name, "base")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007837 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BASE, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007838 goto error;
7839 }
Radek Krejcic1885952017-02-07 09:37:51 +01007840 } else if (!strcmp(node->name, "ordered-by")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007841 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_ORDEREDBY,
7842 "user", "system", LYS_USERORDERED, LYS_USERORDERED, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007843 goto error;
7844 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007845 } else if (!strcmp(node->name, "belongs-to")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007846 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BELONGSTO, 0, "module", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007847 goto error;
7848 }
7849 } else if (!strcmp(node->name, "contact")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007850 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_CONTACT, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007851 goto error;
7852 }
7853 } else if (!strcmp(node->name, "organization")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007854 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ORGANIZATION, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007855 goto error;
7856 }
7857 } else if (!strcmp(node->name, "path")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007858 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PATH, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007859 goto error;
7860 }
Radek Krejcic1885952017-02-07 09:37:51 +01007861 } else if (!strcmp(node->name, "require-instance")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007862 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_REQINSTANCE, "true", "false", unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007863 goto error;
7864 }
7865 } else if (!strcmp(node->name, "modifier")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007866 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_MODIFIER, "invert-match", NULL, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007867 goto error;
7868 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007869 } else if (!strcmp(node->name, "fraction-digits")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007870 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_DIGITS, uint8_t);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007871
7872 GETVAL(value, node, "value");
7873 v = strtol(value, NULL, 10);
7874
7875 /* range check */
7876 if (v < 1 || v > 18) {
7877 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
7878 goto error;
7879 }
7880
7881 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, i, unres)) {
7882 goto error;
7883 }
7884
7885 /* store the value */
7886 (*(uint8_t *)p) = (uint8_t)v;
7887
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007888 YIN_EXTCOMPLEX_ENLARGE(uint8_t);
Radek Krejci5496fae2017-02-10 13:26:48 +01007889 } else if (!strcmp(node->name, "max-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007890 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MAX, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007891
7892 GETVAL(value, node, "value");
7893 while (isspace(value[0])) {
7894 value++;
7895 }
7896
7897 if (!strcmp(value, "unbounded")) {
7898 u = 0;
7899 } else {
7900 /* convert it to uint32_t */
7901 errno = 0; endptr = NULL;
7902 u = strtoul(value, &endptr, 10);
7903 if (*endptr || value[0] == '-' || errno || u == 0 || u > UINT32_MAX) {
7904 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007905 goto error;
7906 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007907 }
Radek Krejci5496fae2017-02-10 13:26:48 +01007908
7909 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
7910 goto error;
7911 }
7912
7913 /* store the value */
Radek Krejcif8d05c22017-02-10 15:33:35 +01007914 *(uint32_t **)p = malloc(sizeof(uint32_t));
7915 (**(uint32_t **)p) = (uint32_t)u;
Radek Krejci5496fae2017-02-10 13:26:48 +01007916
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007917 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007918 } else if (!strcmp(node->name, "min-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007919 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MIN, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007920
7921 GETVAL(value, node, "value");
7922 while (isspace(value[0])) {
7923 value++;
7924 }
7925
7926 /* convert it to uint32_t */
7927 errno = 0;
7928 endptr = NULL;
7929 u = strtoul(value, &endptr, 10);
7930 if (*endptr || value[0] == '-' || errno || u > UINT32_MAX) {
7931 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
7932 goto error;
7933 }
7934
7935 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
7936 goto error;
7937 }
7938
7939 /* store the value */
Radek Krejcif8d05c22017-02-10 15:33:35 +01007940 *(uint32_t **)p = malloc(sizeof(uint32_t));
7941 (**(uint32_t **)p) = (uint32_t)u;
Radek Krejci5496fae2017-02-10 13:26:48 +01007942
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007943 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci06a9aa02017-02-17 10:50:24 +01007944 } else if (!strcmp(node->name, "value")) {
PavolVican2ed9f4e2017-02-16 00:08:45 +01007945 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_VALUE, int32_t*);
7946
7947 GETVAL(value, node, "value");
7948 while (isspace(value[0])) {
7949 value++;
7950 }
7951
7952 /* convert it to int32_t */
Radek Krejci9326fc02017-02-16 09:57:40 +01007953 ll = strtoll(value, NULL, 10);
PavolVican2ed9f4e2017-02-16 00:08:45 +01007954
7955 /* range check */
Radek Krejci9326fc02017-02-16 09:57:40 +01007956 if (ll < INT32_MIN || ll > INT32_MAX) {
PavolVican2ed9f4e2017-02-16 00:08:45 +01007957 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
7958 goto error;
7959 }
7960
7961 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_VALUE, i, unres)) {
7962 goto error;
7963 }
7964
7965 /* store the value */
7966 *(int32_t **)p = malloc(sizeof(int32_t));
Radek Krejci9326fc02017-02-16 09:57:40 +01007967 (**(int32_t **)p) = (int32_t)ll;
PavolVican2ed9f4e2017-02-16 00:08:45 +01007968
7969 YIN_EXTCOMPLEX_ENLARGE(int32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007970 } else if (!strcmp(node->name, "position")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007971 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_POSITION, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007972
7973 GETVAL(value, node, "value");
7974 ll = strtoll(value, NULL, 10);
7975
7976 /* range check */
7977 if (ll < 0 || ll > UINT32_MAX) {
7978 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
7979 goto error;
7980 }
7981
7982 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_POSITION, i, unres)) {
7983 goto error;
7984 }
7985
7986 /* store the value */
Radek Krejcif8d05c22017-02-10 15:33:35 +01007987 *(uint32_t **)p = malloc(sizeof(uint32_t));
7988 (**(uint32_t **)p) = (uint32_t)ll;
Radek Krejci5496fae2017-02-10 13:26:48 +01007989
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007990 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci37f9ba32017-02-10 16:50:35 +01007991 } else if (!strcmp(node->name, "module")) {
7992 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MODULE);
7993 if (!pp) {
7994 goto error;
7995 }
7996
7997 *(struct lys_module **)pp = yin_read_module_(mod->ctx, node, NULL, mod->implemented);
7998 if (!(*pp)) {
7999 goto error;
8000 }
Radek Krejcic5cc5302017-02-16 10:07:46 +01008001 } else if (!strcmp(node->name, "when")) {
8002 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_WHEN, struct lys_when*);
8003
8004 *(struct lys_when**)p = read_yin_when(mod, node, unres);
8005 if (!*(struct lys_when**)p) {
8006 goto error;
8007 }
8008
8009 YIN_EXTCOMPLEX_ENLARGE(struct lys_when*);
Radek Krejci7417a082017-02-16 11:07:59 +01008010 } else if (!strcmp(node->name, "revision")) {
8011 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_REVISION, struct lys_revision*);
8012
8013 *(struct lys_revision**)p = calloc(1, sizeof(struct lys_revision));
8014 if (fill_yin_revision(mod, node, *(struct lys_revision**)p, unres)) {
8015 goto error;
8016 }
8017
8018 /* check uniqueness of the revision dates - not required by RFC */
8019 if (pp) {
8020 for (j = 0; j < i; j++) {
8021 if (!strcmp((*(struct lys_revision***)pp)[j]->date, (*(struct lys_revision**)p)->date)) {
8022 LOGWRN("Module's revisions are not unique (%s).", (*(struct lys_revision**)p)->date);
8023 }
8024 }
8025 }
8026
8027 YIN_EXTCOMPLEX_ENLARGE(struct lys_revision*);
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01008028 } else if (!strcmp(node->name, "unique")) {
8029 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_UNIQUE, struct lys_unique*);
8030
8031 *(struct lys_unique**)p = calloc(1, sizeof(struct lys_unique));
8032 if (fill_yin_unique(mod, (struct lys_node*)ext, node, *(struct lys_unique**)p, unres)) {
8033 goto error;
8034 }
8035
8036 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_UNIQUE, i, unres)) {
8037 goto error;
8038 }
8039 YIN_EXTCOMPLEX_ENLARGE(struct lys_unique*);
Radek Krejcif95b6292017-02-13 15:57:37 +01008040 } else if (!strcmp(node->name, "action")) {
8041 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ACTION, read_yin_rpc_action);
8042 } else if (!strcmp(node->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008043 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYDATA, read_yin_anydata, LYS_ANYDATA);
Radek Krejcif95b6292017-02-13 15:57:37 +01008044 } else if (!strcmp(node->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008045 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYXML, read_yin_anydata, LYS_ANYXML);
Radek Krejcif95b6292017-02-13 15:57:37 +01008046 } else if (!strcmp(node->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008047 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CASE, read_yin_case);
Radek Krejcif95b6292017-02-13 15:57:37 +01008048 } else if (!strcmp(node->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008049 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CHOICE, read_yin_choice);
Radek Krejcif95b6292017-02-13 15:57:37 +01008050 } else if (!strcmp(node->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008051 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CONTAINER, read_yin_container);
Radek Krejcif95b6292017-02-13 15:57:37 +01008052 } else if (!strcmp(node->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008053 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_GROUPING, read_yin_grouping);
Radek Krejcif95b6292017-02-13 15:57:37 +01008054 } else if (!strcmp(node->name, "output")) {
8055 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_OUTPUT, read_yin_input_output);
8056 } else if (!strcmp(node->name, "input")) {
8057 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_INPUT, read_yin_input_output);
8058 } else if (!strcmp(node->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008059 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAF, read_yin_leaf);
Radek Krejcif95b6292017-02-13 15:57:37 +01008060 } else if (!strcmp(node->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008061 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAFLIST, read_yin_leaflist);
Radek Krejcif95b6292017-02-13 15:57:37 +01008062 } else if (!strcmp(node->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01008063 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LIST, read_yin_list);
Radek Krejcif95b6292017-02-13 15:57:37 +01008064 } else if (!strcmp(node->name, "notification")) {
8065 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_NOTIFICATION, read_yin_notif);
8066 } else if (!strcmp(node->name, "uses")) {
8067 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_USES, read_yin_uses);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008068 } else if (!strcmp(node->name, "length")) {
8069 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_LENGTH);
8070 } else if (!strcmp(node->name, "must")) {
8071 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MUST);
8072 if (!pp) {
8073 goto error;
8074 }
8075 /* allocate structure for must */
8076 (*pp) = calloc(1, sizeof(struct lys_restr));
8077
8078 if (fill_yin_must(mod, node, *((struct lys_restr **)pp), unres)) {
8079 goto error;
8080 }
8081 } else if (!strcmp(node->name, "pattern")) {
8082 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_PATTERN, struct lys_restr*);
8083 GETVAL(value, node, "value");
8084 if (lyp_check_pattern(value, NULL)) {
8085 goto error;
8086 }
8087
8088 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr));
8089 (*(struct lys_restr **)p)->expr = lydict_insert(mod->ctx, value, 0);
8090
8091 modifier = 0x06; /* ACK */
8092 if (mod->version >= 2) {
8093 name = NULL;
8094 LY_TREE_FOR(node->child, child) {
8095 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
8096 if (name) {
8097 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
8098 goto error;
8099 }
8100
8101 GETVAL(name, child, "value");
8102 if (!strcmp(name, "invert-match")) {
8103 modifier = 0x15; /* NACK */
8104 } else {
8105 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
8106 goto error;
8107 }
8108 /* get extensions of the modifier */
8109 if (lyp_yin_parse_subnode_ext(mod, *(struct lys_restr **)p, LYEXT_PAR_RESTR, child,
8110 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
8111 goto error;
8112 }
8113 }
8114 }
8115 }
8116
8117 /* store the value: modifier byte + value + terminating NULL byte */
8118 (*(struct lys_restr **)p)->expr = malloc((strlen(value) + 2) * sizeof(char));
8119 ((char *)(*(struct lys_restr **)p)->expr)[0] = modifier;
8120 strcpy(&((char *)(*(struct lys_restr **)p)->expr)[1], value);
8121 lydict_insert_zc(mod->ctx, (char *)(*(struct lys_restr **)p)->expr);
8122
8123 /* get possible sub-statements */
8124 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) {
8125 goto error;
8126 }
8127
8128 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
8129 } else if (!strcmp(node->name, "range")) {
8130 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_RANGE);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008131 } else {
Radek Krejci06a9aa02017-02-17 10:50:24 +01008132 LOGERR(LY_SUCCESS, "Extension's substatement \"%s\" not supported.", node->name);
8133 //LOGERR(LY_EINT, "Extension's substatement \"%s\" not supported.", node->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008134 //return EXIT_FAILURE;
8135 }
8136 lyxml_free(mod->ctx, node);
8137 }
8138
PavolVicanc4b798e2017-02-20 23:15:27 +01008139 if (ext->substmt && lyp_mand_check_ext(ext, yin->name)) {
8140 return EXIT_FAILURE;
Radek Krejci06a9aa02017-02-17 10:50:24 +01008141 }
8142
Radek Krejci8d6b7422017-02-03 14:42:13 +01008143 return EXIT_SUCCESS;
8144
8145error:
8146 return EXIT_FAILURE;
8147}