blob: c837e4ba364d4ff7a11a9ea68b747a416140a50b [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
2 * @file yin.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief YIN parser for libyang
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Radek Krejci54f6fb32016-02-24 12:56:39 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
Michal Vasko8de098c2016-02-26 10:00:25 +010011 *
Radek Krejci54f6fb32016-02-24 12:56:39 +010012 * https://opensource.org/licenses/BSD-3-Clause
Radek Krejcida04f4a2015-05-21 12:54:09 +020013 */
14
Radek Krejci812b10a2015-05-28 16:48:25 +020015#include <assert.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020016#include <ctype.h>
Radek Krejci8b4f23c2015-06-02 16:09:25 +020017#include <errno.h>
18#include <limits.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020019#include <stdint.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020020#include <stdlib.h>
21#include <string.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020022#include <stddef.h>
Michal Vasko69068852015-07-13 14:34:31 +020023#include <sys/types.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020024
Radek Krejci998a0b82015-08-17 13:14:36 +020025#include "libyang.h"
26#include "common.h"
27#include "context.h"
Radek Krejci41912fe2015-10-22 10:22:12 +020028#include "dict_private.h"
Michal Vaskofcdac172015-10-07 09:35:05 +020029#include "xpath.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020030#include "parser.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020031#include "resolve.h"
32#include "tree_internal.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020033#include "xml_internal.h"
Radek Krejciefdd0ce2015-05-26 16:48:29 +020034
Radek Krejciadb57612016-02-16 13:34:34 +010035#define GETVAL(value, node, arg) \
36 value = lyxml_get_attr(node, arg, NULL); \
37 if (!value) { \
Radek Krejci48464ed2016-03-17 15:44:09 +010038 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, arg, node->name); \
Radek Krejciadb57612016-02-16 13:34:34 +010039 goto error; \
Michal Vasko2d710f32016-02-05 12:29:21 +010040 }
Radek Krejcice7fb782015-05-29 16:52:34 +020041
Michal Vaskoe022a562016-09-27 14:24:15 +020042#define OPT_IDENT 0x01
43#define OPT_CFG_PARSE 0x02
44#define OPT_CFG_INHERIT 0x04
45#define OPT_CFG_IGNORE 0x08
46#define OPT_MODULE 0x10
Radek Krejci07d0fb92017-01-13 14:11:05 +010047static int read_yin_common(struct lys_module *, struct lys_node *, void *, LYEXT_PAR, struct lyxml_elem *, int,
48 struct unres_schema *);
Radek Krejcib388c152015-06-04 17:03:03 +020049
Radek Krejcib8048692015-08-05 13:36:34 +020050static struct lys_node *read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020051 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020052static struct lys_node *read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020053 int valid_config, struct unres_schema *unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +020054static struct lys_node *read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020055 LYS_NODE type, int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020056static struct lys_node *read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020057 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020058static struct lys_node *read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020059 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020060static struct lys_node *read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020061 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020062static struct lys_node *read_yin_list(struct lys_module *module,struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020063 int valid_config, struct unres_schema *unres);
Radek Krejcia9544502015-08-14 08:24:29 +020064static struct lys_node *read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci3440cc52016-06-23 17:03:59 +020065 struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020066static struct lys_node *read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020067 int valid_config, struct unres_schema *unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +020068static struct lys_node *read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020069 struct unres_schema *unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +020070static struct lys_node *read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020071 struct unres_schema *unres);
Radek Krejci5323b492017-01-16 15:40:11 +010072static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres);
Radek Krejci74705112015-06-05 10:25:44 +020073
Radek Krejci07d0fb92017-01-13 14:11:05 +010074/*
75 * yin - the provided XML subtree is unlinked
Radek Krejci2b999ac2017-01-18 16:22:12 +010076 * ext - pointer to the storage in the parent structure to be able to update its location after realloc
Radek Krejci07d0fb92017-01-13 14:11:05 +010077 */
78int
79lyp_yin_fill_ext(void *parent, LYEXT_PAR parent_type, LYEXT_SUBSTMT substmt, uint8_t substmt_index,
Radek Krejci2b999ac2017-01-18 16:22:12 +010080 struct lys_module *module, struct lyxml_elem *yin, struct lys_ext_instance ***ext,
81 uint8_t ext_index, struct unres_schema *unres)
Radek Krejci07d0fb92017-01-13 14:11:05 +010082{
83 struct unres_ext *info;
84
85 info = malloc(sizeof *info);
86 lyxml_unlink(module->ctx, yin);
87 info->data.yin = yin;
88 info->datatype = LYS_IN_YIN;
89 info->parent = parent;
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 Krejci51673202016-11-01 17:00:32 +01001604 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&tpdf->dflt)) == -1) {
Michal Vasko478c4652016-07-21 12:55:01 +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;
3003 lys_set_implemented(mod);
3004 }
3005 }
3006
Radek Krejcid5a5c282016-08-15 15:38:08 +02003007 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02003008 return EXIT_SUCCESS;
3009
3010error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02003011 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02003012 return EXIT_FAILURE;
3013}
3014
Michal Vasko0d343d12015-08-24 14:57:36 +02003015/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02003016static int
Radek Krejcib8048692015-08-05 13:36:34 +02003017fill_yin_augment(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_node_augment *aug,
Michal Vaskof02e3742015-08-05 16:27:02 +02003018 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02003019{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003020 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003021 struct lyxml_elem *sub, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003022 struct lys_node *node;
Radek Krejcie534c132016-11-23 13:32:31 +01003023 int ret, c_ftrs = 0, c_ext = 0;
Radek Krejci30701b42017-01-23 16:41:38 +01003024 void *reallocated;
Radek Krejci106efc02015-06-10 14:36:27 +02003025
Michal Vasko591e0b22015-08-13 13:53:43 +02003026 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003027 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003028 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02003029 if (!aug->target_name) {
3030 goto error;
3031 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003032 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02003033
Radek Krejci07d0fb92017-01-13 14:11:05 +01003034 if (read_yin_common(module, NULL, aug, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003035 goto error;
3036 }
3037
Radek Krejcie534c132016-11-23 13:32:31 +01003038 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3039 if (strcmp(sub->ns->value, LY_NSYIN)) {
3040 /* extension */
3041 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003042 continue;
Radek Krejci30701b42017-01-23 16:41:38 +01003043 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejcie534c132016-11-23 13:32:31 +01003044 c_ftrs++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003045 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003046 } else if (!strcmp(sub->name, "when")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003047 if (aug->when) {
Radek Krejcie534c132016-11-23 13:32:31 +01003048 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003049 goto error;
3050 }
3051
Radek Krejci5323b492017-01-16 15:40:11 +01003052 aug->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003053 if (!aug->when) {
Radek Krejcie534c132016-11-23 13:32:31 +01003054 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003055 goto error;
3056 }
Radek Krejcie534c132016-11-23 13:32:31 +01003057 lyxml_free(module->ctx, sub);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003058 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003059
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003060 /* check allowed data sub-statements */
Radek Krejcie534c132016-11-23 13:32:31 +01003061 } else if (!strcmp(sub->name, "container")) {
3062 node = read_yin_container(module, (struct lys_node *)aug, sub, 1, unres);
3063 } else if (!strcmp(sub->name, "leaf-list")) {
3064 node = read_yin_leaflist(module, (struct lys_node *)aug, sub, 1, unres);
3065 } else if (!strcmp(sub->name, "leaf")) {
3066 node = read_yin_leaf(module, (struct lys_node *)aug, sub, 1, unres);
3067 } else if (!strcmp(sub->name, "list")) {
3068 node = read_yin_list(module, (struct lys_node *)aug, sub, 1, unres);
3069 } else if (!strcmp(sub->name, "uses")) {
3070 node = read_yin_uses(module, (struct lys_node *)aug, sub, unres);
3071 } else if (!strcmp(sub->name, "choice")) {
3072 node = read_yin_choice(module, (struct lys_node *)aug, sub, 1, unres);
3073 } else if (!strcmp(sub->name, "case")) {
3074 node = read_yin_case(module, (struct lys_node *)aug, sub, 1, unres);
3075 } else if (!strcmp(sub->name, "anyxml")) {
3076 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYXML, 1, unres);
3077 } else if (!strcmp(sub->name, "anydata")) {
3078 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYDATA, 1, unres);
3079 } else if (!strcmp(sub->name, "action")) {
3080 node = read_yin_rpc_action(module, (struct lys_node *)aug, sub, unres);
3081 } else if (!strcmp(sub->name, "notification")) {
3082 node = read_yin_notif(module, (struct lys_node *)aug, sub, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003083 } else {
Radek Krejcie534c132016-11-23 13:32:31 +01003084 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003085 goto error;
3086 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003087
Radek Krejci1d82ef62015-08-07 14:44:40 +02003088 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003089 goto error;
3090 }
3091
Radek Krejci1d82ef62015-08-07 14:44:40 +02003092 node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01003093 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003094 }
3095
Radek Krejcie534c132016-11-23 13:32:31 +01003096 if (c_ftrs) {
3097 aug->iffeature = calloc(c_ftrs, sizeof *aug->iffeature);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003098 if (!aug->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003099 LOGMEM;
3100 goto error;
3101 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003102 }
Radek Krejcie534c132016-11-23 13:32:31 +01003103 if (c_ext) {
Radek Krejci30701b42017-01-23 16:41:38 +01003104 /* some extensions may be already present from the substatements */
3105 reallocated = realloc(aug->ext, (c_ext + aug->ext_size) * sizeof *aug->ext);
3106 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003107 LOGMEM;
3108 goto error;
3109 }
Radek Krejci30701b42017-01-23 16:41:38 +01003110 aug->ext = reallocated;
3111
3112 /* init memory */
3113 memset(&aug->ext[aug->ext_size], 0, c_ext * sizeof *aug->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003114 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003115
Radek Krejcie534c132016-11-23 13:32:31 +01003116 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3117 if (strcmp(sub->ns->value, LY_NSYIN)) {
3118 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003119 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 +01003120 aug->ext_size++;
3121 if (ret) {
3122 goto error;
3123 }
3124 } else if (!strcmp(sub->name, "if-feature")) {
3125 ret = fill_yin_iffeature((struct lys_node *)aug, 0, sub, &aug->iffeature[aug->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003126 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003127 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003128 goto error;
3129 }
Radek Krejcie534c132016-11-23 13:32:31 +01003130 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003131 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003132 }
3133
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003134 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02003135 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02003136 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02003137 * when the uses does and cannot be resolved now for sure
3138 * (the grouping was not yet copied into uses).
3139 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02003140 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003141 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02003142 goto error;
3143 }
Michal Vasko49291b32015-08-06 09:49:41 +02003144 }
Radek Krejci106efc02015-06-10 14:36:27 +02003145
Michal Vasko508a50d2016-09-07 14:50:33 +02003146 /* check XPath dependencies */
3147 if (aug->when && (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1)) {
3148 goto error;
3149 }
3150
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003151 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02003152
3153error:
3154
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003155 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02003156}
3157
Michal Vasko0d343d12015-08-24 14:57:36 +02003158/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003159static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02003160fill_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 +02003161{
Radek Krejci363bd4a2016-07-29 14:30:20 +02003162 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003163 struct lyxml_elem *sub, *next;
3164 const char *value;
3165 char *endptr;
3166 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01003167 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003168 int r;
3169 unsigned long int val;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003170 void *reallocated;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003171
Radek Krejci363bd4a2016-07-29 14:30:20 +02003172 assert(uses);
3173 module = uses->module; /* shorthand */
3174
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003175 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003176 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02003177 if (!rfn->target_name) {
3178 goto error;
3179 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003180
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003181 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003182 if (!sub->ns) {
3183 /* garbage */
3184 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01003185 /* extension */
3186 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003187 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02003188
Radek Krejci411b1bf2017-01-23 16:40:05 +01003189 } else if (!strcmp(sub->name, "description")) {
3190 if (rfn->dsc) {
3191 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3192 goto error;
3193 }
3194
Radek Krejci8d6b7422017-02-03 14:42:13 +01003195 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003196 goto error;
3197 }
3198
3199 rfn->dsc = read_yin_subnode(module->ctx, sub, "text");
3200 if (!rfn->dsc) {
3201 goto error;
3202 }
3203 } else if (!strcmp(sub->name, "reference")) {
3204 if (rfn->ref) {
3205 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3206 goto error;
3207 }
3208
Radek Krejci8d6b7422017-02-03 14:42:13 +01003209 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003210 goto error;
3211 }
3212
3213 rfn->ref = read_yin_subnode(module->ctx, sub, "text");
3214 if (!rfn->ref) {
3215 goto error;
3216 }
3217 } else if (!strcmp(sub->name, "config")) {
3218 if (rfn->flags & LYS_CONFIG_MASK) {
3219 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3220 goto error;
3221 }
3222 GETVAL(value, sub, "value");
3223 if (!strcmp(value, "false")) {
3224 rfn->flags |= LYS_CONFIG_R;
3225 } else if (!strcmp(value, "true")) {
3226 rfn->flags |= LYS_CONFIG_W;
3227 } else {
3228 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3229 goto error;
3230 }
3231 rfn->flags |= LYS_CONFIG_SET;
3232
Radek Krejci8d6b7422017-02-03 14:42:13 +01003233 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003234 goto error;
3235 }
Radek Krejcie534c132016-11-23 13:32:31 +01003236 } else if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02003237 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02003238
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003239 /* check possibility of statements combination */
3240 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02003241 if (c_dflt) {
3242 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003243 if (module->version < 2) {
3244 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3245 goto error;
3246 }
Radek Krejci200bf712016-08-16 17:11:04 +02003247 rfn->target_type &= LYS_LEAFLIST;
3248 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003249 if (module->version < 2) {
3250 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
3251 } else {
3252 /* YANG 1.1 */
3253 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
3254 }
Radek Krejci200bf712016-08-16 17:11:04 +02003255 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003256 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003257 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3258 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003259 goto error;
3260 }
3261 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003262 if (module->version < 2) {
3263 rfn->target_type = LYS_LEAF | LYS_CHOICE;
3264 } else {
3265 /* YANG 1.1 */
3266 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
3267 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003268 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003269
Radek Krejci8d6b7422017-02-03 14:42:13 +01003270 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 +01003271 goto error;
3272 }
Radek Krejci200bf712016-08-16 17:11:04 +02003273 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003274 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003275 } else if (!strcmp(sub->name, "mandatory")) {
3276 /* leaf, choice or anyxml */
3277 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003278 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003279 goto error;
3280 }
3281 /* just checking the flags in leaf is not sufficient, we would allow
3282 * multiple mandatory statements with the "false" value
3283 */
3284 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003286 /* check possibility of statements combination */
3287 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003288 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003289 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003290 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3291 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003292 goto error;
3293 }
3294 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003295 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003296 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003298 GETVAL(value, sub, "value");
3299 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003300 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003301 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003302 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003303 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003304 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003305 goto error;
3306 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003307 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003308 goto error;
3309 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003310 } else if (!strcmp(sub->name, "min-elements")) {
3311 /* list or leaf-list */
3312 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003313 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003314 goto error;
3315 }
3316 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003317
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003318 /* check possibility of statements combination */
3319 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003320 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003321 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003322 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3323 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003324 goto error;
3325 }
3326 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003327 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003328 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003329
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003330 GETVAL(value, sub, "value");
3331 while (isspace(value[0])) {
3332 value++;
3333 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003334
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003335 /* convert it to uint32_t */
3336 errno = 0;
3337 endptr = NULL;
3338 val = strtoul(value, &endptr, 10);
3339 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003340 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003341 goto error;
3342 }
3343 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003344 rfn->flags |= LYS_RFN_MINSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003345
Radek Krejci8d6b7422017-02-03 14:42:13 +01003346 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003347 goto error;
3348 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003349 } else if (!strcmp(sub->name, "max-elements")) {
3350 /* list or leaf-list */
3351 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003352 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003353 goto error;
3354 }
3355 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003357 /* check possibility of statements combination */
3358 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003359 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003360 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003361 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3362 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003363 goto error;
3364 }
3365 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003366 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003367 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003368
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003369 GETVAL(value, sub, "value");
3370 while (isspace(value[0])) {
3371 value++;
3372 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003373
Radek Krejci0d7b2472016-02-12 11:11:03 +01003374 if (!strcmp(value, "unbounded")) {
3375 rfn->mod.list.max = 0;
3376 } else {
3377 /* convert it to uint32_t */
3378 errno = 0;
3379 endptr = NULL;
3380 val = strtoul(value, &endptr, 10);
3381 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003382 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003383 goto error;
3384 }
3385 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003386 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003387 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003388
Radek Krejci8d6b7422017-02-03 14:42:13 +01003389 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003390 goto error;
3391 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003392 } else if (!strcmp(sub->name, "presence")) {
3393 /* container */
3394 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003395 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003396 goto error;
3397 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003398
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003399 /* check possibility of statements combination */
3400 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003401 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003402 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003403 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3404 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003405 goto error;
3406 }
3407 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003408 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003409 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003410
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003411 GETVAL(value, sub, "value");
3412 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcifdc0d702017-01-23 15:58:38 +01003413
Radek Krejci8d6b7422017-02-03 14:42:13 +01003414 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003415 goto error;
3416 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003417 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02003418 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003419 /* check possibility of statements combination */
3420 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003421 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003422 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003423 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3424 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003425 goto error;
3426 }
3427 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003428 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003429 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003430
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003431 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003432 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003433
Radek Krejci363bd4a2016-07-29 14:30:20 +02003434 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
3435 /* leaf, leaf-list, list, container or anyxml */
3436 /* check possibility of statements combination */
3437 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003438 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003439 if (!rfn->target_type) {
3440 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3441 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
3442 goto error;
3443 }
3444 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003445 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003446 }
3447
3448 c_ftrs++;
3449 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003450 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003451 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003452 goto error;
3453 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003454
Michal Vasko345da0a2015-12-02 10:35:55 +01003455 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003456 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003457
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003458 /* process nodes with cardinality of 0..n */
3459 if (c_must) {
3460 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003461 if (!rfn->must) {
3462 LOGMEM;
3463 goto error;
3464 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003465 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02003466 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02003467 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003468 if (!rfn->iffeature) {
3469 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02003470 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003471 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003472 }
Radek Krejci200bf712016-08-16 17:11:04 +02003473 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003474 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Radek Krejci200bf712016-08-16 17:11:04 +02003475 if (!rfn->dflt) {
3476 LOGMEM;
3477 goto error;
3478 }
3479 }
Radek Krejcie534c132016-11-23 13:32:31 +01003480 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003481 /* some extensions may be already present from the substatements */
3482 reallocated = realloc(rfn->ext, (c_ext + rfn->ext_size) * sizeof *rfn->ext);
3483 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003484 LOGMEM;
3485 goto error;
3486 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01003487 rfn->ext = reallocated;
3488
3489 /* init memory */
3490 memset(&rfn->ext[rfn->ext_size], 0, c_ext * sizeof *rfn->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003491 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003492
Radek Krejcie534c132016-11-23 13:32:31 +01003493 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3494 if (strcmp(sub->ns->value, LY_NSYIN)) {
3495 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003496 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 +01003497 rfn->ext_size++;
3498 if (r) {
3499 goto error;
3500 }
3501 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003502 r = fill_yin_iffeature(uses, 0, sub, &rfn->iffeature[rfn->iffeature_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003503 rfn->iffeature_size++;
3504 if (r) {
3505 goto error;
3506 }
Radek Krejci200bf712016-08-16 17:11:04 +02003507 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01003508 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003509 rfn->must_size++;
3510 if (r) {
3511 goto error;
3512 }
Radek Krejci200bf712016-08-16 17:11:04 +02003513 } else { /* default */
3514 GETVAL(value, sub, "value");
3515
3516 /* check for duplicity */
3517 for (r = 0; r < rfn->dflt_size; r++) {
3518 if (ly_strequal(rfn->dflt[r], value, 1)) {
3519 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3520 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
3521 goto error;
3522 }
3523 }
3524 rfn->dflt[rfn->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02003525 }
3526 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003527
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003528 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003529
3530error:
3531
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003532 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003533}
3534
Michal Vasko0d343d12015-08-24 14:57:36 +02003535/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003536static int
Radek Krejcie534c132016-11-23 13:32:31 +01003537fill_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 +02003538{
Radek Krejcie534c132016-11-23 13:32:31 +01003539 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003540 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003541 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003542 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003543
Radek Krejcie534c132016-11-23 13:32:31 +01003544 /* init */
3545 memset(&exts, 0, sizeof exts);
3546
3547 LY_TREE_FOR_SAFE(yin->child, next, child) {
3548 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003549 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003550 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003551 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3552 /* extension */
3553 c_ext++;
3554 lyxml_unlink_elem(module->ctx, child, 2);
3555 lyxml_add_child(module->ctx, &exts, child);
3556 } else if (!strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003557 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01003558 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003559 goto error;
3560 }
3561 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01003562
Radek Krejci8d6b7422017-02-03 14:42:13 +01003563 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003564 goto error;
3565 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003566 } else if (!strcmp(child->name, "revision-date")) {
3567 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02003568 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3569 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003570 }
3571 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003572 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003573 goto error;
3574 }
3575 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003576
Radek Krejci8d6b7422017-02-03 14:42:13 +01003577 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003578 goto error;
3579 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003580 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003581 if (imp->dsc) {
3582 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3583 goto error;
3584 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003585 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003586 goto error;
3587 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003588 imp->dsc = read_yin_subnode(module->ctx, child, "text");
3589 if (!imp->dsc) {
3590 goto error;
3591 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003592 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003593 if (imp->ref) {
3594 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3595 goto error;
3596 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003597 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003598 goto error;
3599 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003600 imp->ref = read_yin_subnode(module->ctx, child, "text");
3601 if (!imp->ref) {
3602 goto error;
3603 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003604 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003605 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003606 goto error;
3607 }
3608 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003609
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003610 /* check mandatory information */
3611 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003612 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003613 goto error;
3614 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003615
Radek Krejcie534c132016-11-23 13:32:31 +01003616 /* process extensions */
3617 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003618 /* some extensions may be already present from the substatements */
3619 reallocated = realloc(imp->ext, (c_ext + imp->ext_size) * sizeof *imp->ext);
3620 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003621 LOGMEM;
3622 goto error;
3623 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003624 imp->ext = reallocated;
3625
3626 /* init memory */
3627 memset(&imp->ext[imp->ext_size], 0, c_ext * sizeof *imp->ext);
3628
Radek Krejcie534c132016-11-23 13:32:31 +01003629 LY_TREE_FOR_SAFE(exts.child, next, child) {
3630 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003631 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 +01003632 imp->ext_size++;
3633 if (r) {
3634 goto error;
3635 }
3636 }
3637 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003638
Radek Krejcie534c132016-11-23 13:32:31 +01003639 GETVAL(value, yin, "module");
Pavol Vicane994fda2016-03-22 10:47:58 +01003640 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02003641
3642error:
3643
Radek Krejcie534c132016-11-23 13:32:31 +01003644 while (exts.child) {
3645 lyxml_free(module->ctx, exts.child);
3646 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003647 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02003648}
3649
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003650/* logs directly
3651 * returns:
3652 * 0 - inc successfully filled
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003653 * -1 - error
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003654 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003655static int
Michal Vasko5ff78822016-02-12 09:33:31 +01003656fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
3657 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02003658{
Radek Krejcie534c132016-11-23 13:32:31 +01003659 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003660 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003661 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003662 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003663
Radek Krejcie534c132016-11-23 13:32:31 +01003664 /* init */
3665 memset(&exts, 0, sizeof exts);
3666
3667 LY_TREE_FOR_SAFE(yin->child, next, child) {
3668 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003669 /* garbage */
3670 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003671 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3672 /* extension */
3673 c_ext++;
3674 lyxml_unlink_elem(module->ctx, child, 2);
3675 lyxml_add_child(module->ctx, &exts, child);
3676 } else if (!strcmp(child->name, "revision-date")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003677 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003678 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003679 goto error;
3680 }
3681 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003682 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003683 goto error;
3684 }
3685 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003686
Radek Krejci8d6b7422017-02-03 14:42:13 +01003687 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003688 goto error;
3689 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003690 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003691 if (inc->dsc) {
3692 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3693 goto error;
3694 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003695 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003696 goto error;
3697 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003698 inc->dsc = read_yin_subnode(module->ctx, child, "text");
3699 if (!inc->dsc) {
3700 goto error;
3701 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003702 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003703 if (inc->ref) {
3704 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3705 goto error;
3706 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003707 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003708 goto error;
3709 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003710 inc->ref = read_yin_subnode(module->ctx, child, "text");
3711 if (!inc->ref) {
3712 goto error;
3713 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003714 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003715 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003716 goto error;
3717 }
3718 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003719
Radek Krejcie534c132016-11-23 13:32:31 +01003720 /* process extensions */
3721 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003722 /* some extensions may be already present from the substatements */
3723 reallocated = realloc(inc->ext, (c_ext + inc->ext_size) * sizeof *inc->ext);
3724 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003725 LOGMEM;
3726 goto error;
3727 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003728 inc->ext = reallocated;
3729
3730 /* init memory */
3731 memset(&inc->ext[inc->ext_size], 0, c_ext * sizeof *inc->ext);
3732
Radek Krejcie534c132016-11-23 13:32:31 +01003733 LY_TREE_FOR_SAFE(exts.child, next, child) {
3734 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003735 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 +01003736 inc->ext_size++;
3737 if (r) {
3738 goto error;
3739 }
3740 }
3741 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003742
Radek Krejcie534c132016-11-23 13:32:31 +01003743 GETVAL(value, yin, "module");
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003744 return lyp_check_include(submodule ? (struct lys_module *)submodule : module, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02003745
3746error:
3747
Radek Krejci83e3f5b2016-06-24 14:55:25 +02003748 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02003749}
3750
Michal Vasko0d343d12015-08-24 14:57:36 +02003751/* logs directly
3752 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003753 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02003754 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02003755 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003756 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003757static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01003758read_yin_common(struct lys_module *module, struct lys_node *parent, void *stmt, LYEXT_PAR stmt_type,
3759 struct lyxml_elem *xmlnode, int opt, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003760{
Radek Krejci07d0fb92017-01-13 14:11:05 +01003761 struct lys_node *node = stmt;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003762 const char *value;
3763 struct lyxml_elem *sub, *next;
3764 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003765
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003766 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003767 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003768 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003770 if (opt & OPT_IDENT) {
3771 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01003772 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003773 goto error;
3774 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003775 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003776 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003777
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003778 /* process local parameters */
3779 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003780 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003781 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003782 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02003783 continue;
3784 }
3785 if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejci6ff885d2017-01-03 14:06:22 +01003786 /* possibly an extension, keep the node for later processing, so skipping lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003787 continue;
3788 }
3789
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003790 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003791 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003792 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003793 goto error;
3794 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003795
Radek Krejci8d6b7422017-02-03 14:42:13 +01003796 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003797 goto error;
3798 }
3799
Radek Krejci1d82ef62015-08-07 14:44:40 +02003800 node->dsc = read_yin_subnode(ctx, sub, "text");
3801 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003802 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003803 }
3804 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003805 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003806 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003807 goto error;
3808 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003809
Radek Krejci8d6b7422017-02-03 14:42:13 +01003810 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003811 goto error;
3812 }
3813
Radek Krejci1d82ef62015-08-07 14:44:40 +02003814 node->ref = read_yin_subnode(ctx, sub, "text");
3815 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003816 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003817 }
3818 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003819 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003820 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003821 goto error;
3822 }
3823 GETVAL(value, sub, "value");
3824 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003825 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003826 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003827 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003828 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003829 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003830 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003831 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003832 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003833 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003834
Radek Krejci8d6b7422017-02-03 14:42:13 +01003835 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_STATUS, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003836 goto error;
3837 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003838 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3839 if (opt & OPT_CFG_PARSE) {
3840 if (node->flags & LYS_CONFIG_MASK) {
3841 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
3842 goto error;
3843 }
3844 GETVAL(value, sub, "value");
3845 if (!strcmp(value, "false")) {
3846 node->flags |= LYS_CONFIG_R;
3847 } else if (!strcmp(value, "true")) {
3848 node->flags |= LYS_CONFIG_W;
3849 } else {
3850 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3851 goto error;
3852 }
3853 node->flags |= LYS_CONFIG_SET;
Radek Krejci07d0fb92017-01-13 14:11:05 +01003854
Radek Krejci8d6b7422017-02-03 14:42:13 +01003855 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003856 goto error;
3857 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003858 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003859 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003860 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003861 continue;
3862 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003863 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003864 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003865
Michal Vaskoe022a562016-09-27 14:24:15 +02003866 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003867 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02003868 if (parent) {
3869 node->flags |= parent->flags & LYS_CONFIG_MASK;
3870 } else if (!parent) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003871 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003872 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003873 }
3874 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003875
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003876 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02003877
3878error:
3879
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003880 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003881}
3882
Michal Vasko0d343d12015-08-24 14:57:36 +02003883/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003884static struct lys_when *
Radek Krejci5323b492017-01-16 15:40:11 +01003885read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003886{
Radek Krejci76512572015-08-04 09:47:08 +02003887 struct lys_when *retval = NULL;
Radek Krejci5323b492017-01-16 15:40:11 +01003888 struct lyxml_elem *child, *next;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003889 const char *value;
3890
3891 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01003892 if (!retval) {
3893 LOGMEM;
3894 return NULL;
3895 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003896
3897 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01003898 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02003899 if (!retval->cond) {
3900 goto error;
3901 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003902
Radek Krejci5323b492017-01-16 15:40:11 +01003903 LY_TREE_FOR_SAFE(yin->child, next, child) {
3904 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003905 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003906 continue;
Radek Krejci5323b492017-01-16 15:40:11 +01003907 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3908 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01003909 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003910 goto error;
3911 }
3912 } else if (!strcmp(child->name, "description")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003913 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003914 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003915 goto error;
3916 }
Radek Krejci5323b492017-01-16 15:40:11 +01003917
Radek Krejci8d6b7422017-02-03 14:42:13 +01003918 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003919 goto error;
3920 }
3921
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003922 retval->dsc = read_yin_subnode(module->ctx, child, "text");
3923 if (!retval->dsc) {
3924 goto error;
3925 }
3926 } else if (!strcmp(child->name, "reference")) {
3927 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003928 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003929 goto error;
3930 }
Radek Krejci5323b492017-01-16 15:40:11 +01003931
Radek Krejci8d6b7422017-02-03 14:42:13 +01003932 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003933 goto error;
3934 }
3935
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003936 retval->ref = read_yin_subnode(module->ctx, child, "text");
3937 if (!retval->ref) {
3938 goto error;
3939 }
3940 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003941 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003942 goto error;
3943 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003944 }
3945
3946 return retval;
3947
3948error:
3949
Michal Vasko0308dd62015-10-07 09:14:40 +02003950 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003951 return NULL;
3952}
3953
Michal Vasko0d343d12015-08-24 14:57:36 +02003954/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003955static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003956read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02003957 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02003958{
Michal Vasko29fc0182015-08-24 15:02:39 +02003959 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003960 struct lys_node_case *cs;
3961 struct lys_node *retval, *node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01003962 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01003963 void *reallocated;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003964
Radek Krejcie867c852015-08-27 09:52:34 +02003965 /* init */
3966 memset(&root, 0, sizeof root);
3967
Radek Krejci1d82ef62015-08-07 14:44:40 +02003968 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01003969 if (!cs) {
3970 LOGMEM;
3971 return NULL;
3972 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003973 cs->nodetype = LYS_CASE;
3974 cs->prev = (struct lys_node *)cs;
3975 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003976
Radek Krejci07d0fb92017-01-13 14:11:05 +01003977 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
3978 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_INHERIT : 0), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003979 goto error;
3980 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003981
Radek Krejcia9544502015-08-14 08:24:29 +02003982 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3983
Michal Vasko3a0043f2015-08-12 12:11:30 +02003984 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003985 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003986 goto error;
3987 }
3988
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003989 /* process choice's specific children */
3990 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01003991 if (strcmp(sub->ns->value, LY_NSYIN)) {
3992 /* extension */
3993 c_ext++;
3994 } else if (!strcmp(sub->name, "container") ||
Michal Vasko29fc0182015-08-24 15:02:39 +02003995 !strcmp(sub->name, "leaf-list") ||
3996 !strcmp(sub->name, "leaf") ||
3997 !strcmp(sub->name, "list") ||
3998 !strcmp(sub->name, "uses") ||
3999 !strcmp(sub->name, "choice") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01004000 !strcmp(sub->name, "anyxml") ||
4001 !strcmp(sub->name, "anydata")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02004002
Michal Vaskof3930de2015-10-22 12:03:59 +02004003 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02004004 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004005 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02004006 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004007 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004008 if (cs->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004009 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004010 goto error;
4011 }
4012
Radek Krejci5323b492017-01-16 15:40:11 +01004013 cs->when = read_yin_when(module, sub, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004014 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004015 goto error;
4016 }
Michal Vasko29fc0182015-08-24 15:02:39 +02004017
Michal Vasko345da0a2015-12-02 10:35:55 +01004018 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004019 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004020 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004021 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004022 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004023 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004024
Radek Krejci3cf9e222015-06-18 11:37:50 +02004025 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004026 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
4027 if (!cs->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004028 LOGMEM;
4029 goto error;
4030 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004031 }
Radek Krejcie534c132016-11-23 13:32:31 +01004032 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004033 /* some extensions may be already present from the substatements */
4034 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4035 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004036 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004037 goto error;
4038 }
Radek Krejci21c81652017-01-23 10:42:55 +01004039 retval->ext = reallocated;
4040
4041 /* init memory */
4042 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004043 }
Radek Krejci21c81652017-01-23 10:42:55 +01004044
Radek Krejcie534c132016-11-23 13:32:31 +01004045 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4046 if (strcmp(sub->ns->value, LY_NSYIN)) {
4047 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004048 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 +01004049 retval->ext_size++;
4050 if (ret) {
4051 goto error;
4052 }
4053 } else {
4054 /* if-feature */
4055 ret = fill_yin_iffeature(retval, 0, sub, &cs->iffeature[cs->iffeature_size], unres);
4056 cs->iffeature_size++;
4057 if (ret) {
4058 goto error;
4059 }
4060 }
4061 }
Radek Krejcib388c152015-06-04 17:03:03 +02004062
Michal Vasko29fc0182015-08-24 15:02:39 +02004063 /* last part - process data nodes */
4064 LY_TREE_FOR_SAFE(root.child, next, sub) {
4065 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004066 node = read_yin_container(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004067 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004068 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004069 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004070 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004071 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004072 node = read_yin_list(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004073 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004074 node = read_yin_choice(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004075 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004076 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004077 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004078 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004079 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004080 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004081 }
4082 if (!node) {
4083 goto error;
4084 }
4085
Michal Vasko345da0a2015-12-02 10:35:55 +01004086 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02004087 }
4088
Michal Vasko508a50d2016-09-07 14:50:33 +02004089 /* check XPath dependencies */
4090 if (cs->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4091 goto error;
4092 }
4093
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004094 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004095
4096error:
4097
Michal Vasko29fc0182015-08-24 15:02:39 +02004098 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004099 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02004100 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004101 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02004102
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004103 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004104}
4105
Michal Vasko0d343d12015-08-24 14:57:36 +02004106/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004107static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004108read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
4109 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004110{
Radek Krejci629cdef2016-06-06 15:06:36 +02004111 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004112 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004113 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02004114 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02004115 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01004116 int f_mand = 0, c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004117 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004118
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004119 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01004120 if (!choice) {
4121 LOGMEM;
4122 return NULL;
4123 }
Radek Krejci76512572015-08-04 09:47:08 +02004124 choice->nodetype = LYS_CHOICE;
4125 choice->prev = (struct lys_node *)choice;
4126 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004127
Radek Krejci07d0fb92017-01-13 14:11:05 +01004128 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4129 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004130 goto error;
4131 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004132
Radek Krejcia9544502015-08-14 08:24:29 +02004133 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4134
Michal Vasko3a0043f2015-08-12 12:11:30 +02004135 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004136 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004137 goto error;
4138 }
4139
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004140 /* process choice's specific children */
4141 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004142 if (strcmp(sub->ns->value, LY_NSYIN)) {
4143 /* extension */
4144 c_ext++;
4145 /* keep it for later processing, skip lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02004146 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004147 } else if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004148 if (!(node = read_yin_container(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004149 goto error;
4150 }
4151 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004152 if (!(node = read_yin_leaflist(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004153 goto error;
4154 }
4155 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004156 if (!(node = read_yin_leaf(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004157 goto error;
4158 }
4159 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004160 if (!(node = read_yin_list(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004161 goto error;
4162 }
4163 } else if (!strcmp(sub->name, "case")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004164 if (!(node = read_yin_case(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004165 goto error;
4166 }
4167 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004168 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004169 goto error;
4170 }
4171 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004172 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004173 goto error;
4174 }
4175 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02004176 if (dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004177 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004178 goto error;
4179 }
Radek Krejci21c81652017-01-23 10:42:55 +01004180
Radek Krejci8d6b7422017-02-03 14:42:13 +01004181 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004182 goto error;
4183 }
4184
Radek Krejci629cdef2016-06-06 15:06:36 +02004185 dflt = sub;
4186 lyxml_unlink_elem(ctx, dflt, 0);
Radek Krejcif9a312c2016-06-06 15:14:30 +02004187 continue;
4188 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
4189
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004190 } else if (!strcmp(sub->name, "mandatory")) {
4191 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004192 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004193 goto error;
4194 }
4195 /* just checking the flags in leaf is not sufficient, we would allow
4196 * multiple mandatory statements with the "false" value
4197 */
4198 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004199
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004200 GETVAL(value, sub, "value");
4201 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004202 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004203 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004204 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004205 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004206 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004207 goto error;
4208 } /* else false is the default value, so we can ignore it */
Radek Krejci21c81652017-01-23 10:42:55 +01004209
Radek Krejci8d6b7422017-02-03 14:42:13 +01004210 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004211 goto error;
4212 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004213 } else if (!strcmp(sub->name, "when")) {
4214 if (choice->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004215 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004216 goto error;
4217 }
4218
Radek Krejci5323b492017-01-16 15:40:11 +01004219 choice->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004220 if (!choice->when) {
4221 goto error;
4222 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004223 } else if (!strcmp(sub->name, "if-feature")) {
4224 c_ftrs++;
4225
Michal Vasko345da0a2015-12-02 10:35:55 +01004226 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02004227 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02004228 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004229 if (!(node = read_yin_choice(module, retval, sub, valid_config, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02004230 goto error;
4231 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004232 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004233 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004234 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004235 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004236
Radek Krejci1d82ef62015-08-07 14:44:40 +02004237 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01004238 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004239 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004240
Radek Krejci3cf9e222015-06-18 11:37:50 +02004241 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004242 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
4243 if (!choice->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004244 LOGMEM;
4245 goto error;
4246 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004247 }
Radek Krejcie534c132016-11-23 13:32:31 +01004248 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004249 /* some extensions may be already present from the substatements */
4250 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4251 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004252 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004253 goto error;
4254 }
Radek Krejci21c81652017-01-23 10:42:55 +01004255 retval->ext = reallocated;
4256
4257 /* init memory */
4258 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004259 }
4260
Radek Krejcie534c132016-11-23 13:32:31 +01004261 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4262 if (strcmp(sub->ns->value, LY_NSYIN)) {
4263 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004264 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 +01004265 retval->ext_size++;
4266 if (ret) {
4267 goto error;
4268 }
4269 } else {
4270 ret = fill_yin_iffeature(retval, 0, sub, &choice->iffeature[choice->iffeature_size], unres);
4271 choice->iffeature_size++;
4272 if (ret) {
4273 goto error;
4274 }
4275 }
4276 }
4277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004278 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02004279 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004280 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "default", "choice");
Michal Vasko51e5c582017-01-19 14:16:39 +01004281 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004282 goto error;
4283 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004285 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02004286 if (dflt) {
4287 GETVAL(value, dflt, "value");
4288 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004289 goto error;
4290 }
Radek Krejci629cdef2016-06-06 15:06:36 +02004291 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004292 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004293
Michal Vasko508a50d2016-09-07 14:50:33 +02004294 /* check XPath dependencies */
4295 if (choice->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4296 goto error;
4297 }
4298
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004299 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004300
4301error:
4302
Radek Krejci629cdef2016-06-06 15:06:36 +02004303 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004304 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004305
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004306 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004307}
4308
Michal Vasko0d343d12015-08-24 14:57:36 +02004309/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004310static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004311read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
4312 int valid_config, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02004313{
Radek Krejci76512572015-08-04 09:47:08 +02004314 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02004315 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004316 struct lyxml_elem *sub, *next;
4317 const char *value;
4318 int r;
4319 int f_mand = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004320 int c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004321 void *reallocated;
Radek Krejci863c2852015-06-03 15:47:11 +02004322
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004323 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01004324 if (!anyxml) {
4325 LOGMEM;
4326 return NULL;
4327 }
Radek Krejcibf2abff2016-08-23 15:51:52 +02004328 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02004329 anyxml->prev = (struct lys_node *)anyxml;
4330 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02004331
Radek Krejci07d0fb92017-01-13 14:11:05 +01004332 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4333 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004334 goto error;
4335 }
Radek Krejci863c2852015-06-03 15:47:11 +02004336
Radek Krejcia9544502015-08-14 08:24:29 +02004337 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004338
Radek Krejcic189a952016-07-11 15:27:07 +02004339 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004340 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004341 goto error;
4342 }
4343
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004344 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004345 if (strcmp(sub->ns->value, LY_NSYIN)) {
4346 /* extension */
4347 c_ext++;
4348 } else if (!strcmp(sub->name, "mandatory")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004349 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004350 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004351 goto error;
4352 }
4353 /* just checking the flags in leaf is not sufficient, we would allow
4354 * multiple mandatory statements with the "false" value
4355 */
4356 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02004357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004358 GETVAL(value, sub, "value");
4359 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004360 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004361 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004362 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004363 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004364 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004365 goto error;
4366 }
4367 /* else false is the default value, so we can ignore it */
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004368
Radek Krejci8d6b7422017-02-03 14:42:13 +01004369 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004370 goto error;
4371 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004372 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004373 } else if (!strcmp(sub->name, "when")) {
4374 if (anyxml->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004375 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004376 goto error;
4377 }
4378
Radek Krejci5323b492017-01-16 15:40:11 +01004379 anyxml->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004380 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004381 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004382 goto error;
4383 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004384 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004385 } else if (!strcmp(sub->name, "must")) {
4386 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004387 } else if (!strcmp(sub->name, "if-feature")) {
4388 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02004389
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004390 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004391 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004392 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004393 }
4394 }
Radek Krejci863c2852015-06-03 15:47:11 +02004395
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004396 /* middle part - process nodes with cardinality of 0..n */
4397 if (c_must) {
4398 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004399 if (!anyxml->must) {
4400 LOGMEM;
4401 goto error;
4402 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004403 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004404 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004405 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
4406 if (!anyxml->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004407 LOGMEM;
4408 goto error;
4409 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004410 }
Radek Krejcie534c132016-11-23 13:32:31 +01004411 if (c_ext) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004412 /* some extensions may be already present from the substatements */
4413 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4414 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004415 LOGMEM;
4416 goto error;
4417 }
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004418 retval->ext = reallocated;
4419
4420 /* init memory */
4421 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004422 }
Radek Krejci863c2852015-06-03 15:47:11 +02004423
Radek Krejcie534c132016-11-23 13:32:31 +01004424 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4425 if (strcmp(sub->ns->value, LY_NSYIN)) {
4426 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004427 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 +01004428 retval->ext_size++;
4429 if (r) {
4430 goto error;
4431 }
4432 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004433 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004434 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004435 if (r) {
4436 goto error;
4437 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004438 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004439 r = fill_yin_iffeature(retval, 0, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004440 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004441 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004442 goto error;
4443 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004444 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004445 }
Radek Krejci863c2852015-06-03 15:47:11 +02004446
Michal Vasko508a50d2016-09-07 14:50:33 +02004447 /* check XPath dependencies */
4448 if ((anyxml->when || anyxml->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4449 goto error;
4450 }
4451
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004452 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02004453
4454error:
4455
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004456 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02004457
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004458 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02004459}
4460
Michal Vasko0d343d12015-08-24 14:57:36 +02004461/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004462static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004463read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004464 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004465{
Radek Krejci76512572015-08-04 09:47:08 +02004466 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004467 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004468 struct lyxml_elem *sub, *next;
4469 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01004470 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004471 int c_must = 0, c_ftrs = 0, f_mand = 0, c_ext = 0;
Radek Krejcifccd1442017-01-16 10:26:57 +01004472 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004473
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004474 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01004475 if (!leaf) {
4476 LOGMEM;
4477 return NULL;
4478 }
Radek Krejci76512572015-08-04 09:47:08 +02004479 leaf->nodetype = LYS_LEAF;
4480 leaf->prev = (struct lys_node *)leaf;
4481 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004482
Radek Krejci07d0fb92017-01-13 14:11:05 +01004483 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4484 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004485 goto error;
4486 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004487
Radek Krejcia9544502015-08-14 08:24:29 +02004488 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004489
Radek Krejcic189a952016-07-11 15:27:07 +02004490 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004491 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004492 goto error;
4493 }
4494
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004495 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004496 if (strcmp(sub->ns->value, LY_NSYIN)) {
4497 /* extension */
4498 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004499 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004500 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004501 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004502 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004503 goto error;
4504 }
Michal Vasko88c29542015-11-27 14:57:53 +01004505 /* HACK for unres */
4506 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004507 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004508 /* postpone type resolution when if-feature parsing is done since we need
4509 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004510 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004511 } else if (!strcmp(sub->name, "default")) {
4512 if (leaf->dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004513 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004514 goto error;
4515 }
4516 GETVAL(value, sub, "value");
4517 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci1abcdae2017-01-18 14:14:18 +01004518
Radek Krejci8d6b7422017-02-03 14:42:13 +01004519 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci1abcdae2017-01-18 14:14:18 +01004520 goto error;
4521 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004522 } else if (!strcmp(sub->name, "units")) {
4523 if (leaf->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004524 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004525 goto error;
4526 }
4527 GETVAL(value, sub, "name");
4528 leaf->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004529
Radek Krejci8d6b7422017-02-03 14:42:13 +01004530 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004531 goto error;
4532 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004533 } else if (!strcmp(sub->name, "mandatory")) {
4534 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004535 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004536 goto error;
4537 }
4538 /* just checking the flags in leaf is not sufficient, we would allow
4539 * multiple mandatory statements with the "false" value
4540 */
4541 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02004542
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004543 GETVAL(value, sub, "value");
4544 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004545 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004546 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004547 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004548 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004549 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004550 goto error;
4551 } /* else false is the default value, so we can ignore it */
Radek Krejcifccd1442017-01-16 10:26:57 +01004552
Radek Krejci8d6b7422017-02-03 14:42:13 +01004553 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004554 goto error;
4555 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004556 } else if (!strcmp(sub->name, "when")) {
4557 if (leaf->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004558 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004559 goto error;
4560 }
4561
Radek Krejci5323b492017-01-16 15:40:11 +01004562 leaf->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004563 if (!leaf->when) {
4564 goto error;
4565 }
4566
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004567 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02004568 c_must++;
4569 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004570 } else if (!strcmp(sub->name, "if-feature")) {
4571 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004572 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004573
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004574 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004575 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004576 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004577 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004578
Michal Vasko88c29542015-11-27 14:57:53 +01004579 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004580 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004581
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004582 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004583 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004584 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004585 goto error;
4586 }
Michal Vasko478c4652016-07-21 12:55:01 +02004587 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004588 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "mandatory", "leaf");
Michal Vasko51e5c582017-01-19 14:16:39 +01004589 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL,
Michal Vasko478c4652016-07-21 12:55:01 +02004590 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
4591 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004592 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004593
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004594 /* middle part - process nodes with cardinality of 0..n */
4595 if (c_must) {
4596 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004597 if (!leaf->must) {
4598 LOGMEM;
4599 goto error;
4600 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004601 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004602 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004603 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
4604 if (!leaf->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004605 LOGMEM;
4606 goto error;
4607 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004608 }
Radek Krejcie534c132016-11-23 13:32:31 +01004609 if (c_ext) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004610 /* some extensions may be already present from the substatements */
4611 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4612 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004613 LOGMEM;
4614 goto error;
4615 }
Radek Krejcifccd1442017-01-16 10:26:57 +01004616 retval->ext = reallocated;
4617
4618 /* init memory */
4619 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004620 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004621
Radek Krejcie534c132016-11-23 13:32:31 +01004622 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4623 if (strcmp(sub->ns->value, LY_NSYIN)) {
4624 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004625 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 +01004626 retval->ext_size++;
4627 if (r) {
4628 goto error;
4629 }
4630 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004631 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004632 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004633 if (r) {
4634 goto error;
4635 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004636 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004637 r = fill_yin_iffeature(retval, 0, sub, &leaf->iffeature[leaf->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004638 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004639 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004640 goto error;
4641 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004642 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004643 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004644
Radek Krejcicbb473e2016-09-16 14:48:32 +02004645 /* finalize type parsing */
4646 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
4647 leaf->type.der = NULL;
4648 goto error;
4649 }
4650
4651 /* check default value (if not defined, there still could be some restrictions
4652 * that need to be checked against a default value from a derived type) */
Radek Krejci51673202016-11-01 17:00:32 +01004653 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt)) == -1) {
Radek Krejcicbb473e2016-09-16 14:48:32 +02004654 goto error;
4655 }
4656
Michal Vasko508a50d2016-09-07 14:50:33 +02004657 /* check XPath dependencies */
4658 if ((leaf->when || leaf->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4659 goto error;
4660 }
4661
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004662 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004663
4664error:
4665
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004666 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004667
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004668 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004669}
4670
Michal Vasko0d343d12015-08-24 14:57:36 +02004671/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004672static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004673read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004674 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004675{
Radek Krejci76512572015-08-04 09:47:08 +02004676 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004677 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004678 struct lyxml_elem *sub, *next;
4679 const char *value;
4680 char *endptr;
4681 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004682 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004683 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004684 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejci5323b492017-01-16 15:40:11 +01004685 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004686
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004687 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01004688 if (!llist) {
4689 LOGMEM;
4690 return NULL;
4691 }
Radek Krejci76512572015-08-04 09:47:08 +02004692 llist->nodetype = LYS_LEAFLIST;
4693 llist->prev = (struct lys_node *)llist;
4694 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004695
Radek Krejci07d0fb92017-01-13 14:11:05 +01004696 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4697 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004698 goto error;
4699 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004700
Radek Krejcia9544502015-08-14 08:24:29 +02004701 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004702
Radek Krejcic189a952016-07-11 15:27:07 +02004703 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004704 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004705 goto error;
4706 }
4707
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004708 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004709 if (strcmp(sub->ns->value, LY_NSYIN)) {
4710 /* extension */
4711 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004712 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004713 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004714 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004715 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004716 goto error;
4717 }
Michal Vasko88c29542015-11-27 14:57:53 +01004718 /* HACK for unres */
4719 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004720 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004721 /* postpone type resolution when if-feature parsing is done since we need
4722 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004723 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004724 } else if (!strcmp(sub->name, "units")) {
4725 if (llist->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004726 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004727 goto error;
4728 }
4729 GETVAL(value, sub, "name");
4730 llist->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004731
Radek Krejci8d6b7422017-02-03 14:42:13 +01004732 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004733 goto error;
4734 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004735 } else if (!strcmp(sub->name, "ordered-by")) {
4736 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004737 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004738 goto error;
4739 }
4740 /* just checking the flags in llist is not sufficient, we would
4741 * allow multiple ordered-by statements with the "system" value
4742 */
4743 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004744
Radek Krejci1574a8d2015-08-03 14:16:52 +02004745 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004746 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4747 * state data
4748 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004749 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004750 continue;
4751 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004752
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004753 GETVAL(value, sub, "value");
4754 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004755 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004756 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004757 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004758 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02004759 } /* else system is the default value, so we can ignore it */
4760
Radek Krejci8d6b7422017-02-03 14:42:13 +01004761 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004762 goto error;
4763 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004764 } else if (!strcmp(sub->name, "must")) {
4765 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02004766 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004767 } else if (!strcmp(sub->name, "if-feature")) {
4768 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004769 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02004770 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004771 /* read the default's extension instances */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004772 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 +01004773 goto error;
4774 }
4775
Radek Krejcid5a5c282016-08-15 15:38:08 +02004776 c_dflt++;
4777 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004778
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004779 } else if (!strcmp(sub->name, "min-elements")) {
4780 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004781 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004782 goto error;
4783 }
4784 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004785
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004786 GETVAL(value, sub, "value");
4787 while (isspace(value[0])) {
4788 value++;
4789 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004790
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004791 /* convert it to uint32_t */
4792 errno = 0;
4793 endptr = NULL;
4794 val = strtoul(value, &endptr, 10);
4795 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004796 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004797 goto error;
4798 }
4799 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004800 if (llist->max && (llist->min > llist->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004801 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004802 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004803 goto error;
4804 }
Radek Krejci5323b492017-01-16 15:40:11 +01004805
Radek Krejci8d6b7422017-02-03 14:42:13 +01004806 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004807 goto error;
4808 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004809 } else if (!strcmp(sub->name, "max-elements")) {
4810 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004811 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004812 goto error;
4813 }
4814 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004815
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004816 GETVAL(value, sub, "value");
4817 while (isspace(value[0])) {
4818 value++;
4819 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004820
Radek Krejci0d7b2472016-02-12 11:11:03 +01004821 if (!strcmp(value, "unbounded")) {
4822 llist->max = 0;
4823 } else {
4824 /* convert it to uint32_t */
4825 errno = 0;
4826 endptr = NULL;
4827 val = strtoul(value, &endptr, 10);
4828 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004829 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004830 goto error;
4831 }
4832 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004833 if (llist->min > llist->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004834 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004835 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004836 goto error;
4837 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004838 }
Radek Krejci5323b492017-01-16 15:40:11 +01004839
Radek Krejci8d6b7422017-02-03 14:42:13 +01004840 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004841 goto error;
4842 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004843 } else if (!strcmp(sub->name, "when")) {
4844 if (llist->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004845 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004846 goto error;
4847 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004848
Radek Krejci5323b492017-01-16 15:40:11 +01004849 llist->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004850 if (!llist->when) {
4851 goto error;
4852 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004853 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004854 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004855 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004856 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004857
Michal Vasko88c29542015-11-27 14:57:53 +01004858 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004859 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004860
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004861 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004862 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004863 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004864 goto error;
4865 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004866
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004867 /* middle part - process nodes with cardinality of 0..n */
4868 if (c_must) {
4869 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004870 if (!llist->must) {
4871 LOGMEM;
4872 goto error;
4873 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004874 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004875 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004876 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
4877 if (!llist->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004878 LOGMEM;
4879 goto error;
4880 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004881 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004882 if (c_dflt) {
4883 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
4884 if (!llist->dflt) {
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004885 LOGMEM;
4886 goto error;
4887 }
4888 }
Radek Krejcie534c132016-11-23 13:32:31 +01004889 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01004890 /* some extensions may be already present from the substatements */
4891 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4892 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004893 LOGMEM;
4894 goto error;
4895 }
Radek Krejci5323b492017-01-16 15:40:11 +01004896 retval->ext = reallocated;
4897
4898 /* init memory */
4899 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004900 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004901
Radek Krejcie534c132016-11-23 13:32:31 +01004902 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4903 if (strcmp(sub->ns->value, LY_NSYIN)) {
4904 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004905 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 +01004906 retval->ext_size++;
4907 if (r) {
4908 goto error;
4909 }
4910 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004911 r = fill_yin_must(module, sub, &llist->must[llist->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004912 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004913 if (r) {
4914 goto error;
4915 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004916 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004917 r = fill_yin_iffeature(retval, 0, sub, &llist->iffeature[llist->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004918 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004919 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004920 goto error;
4921 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004922 } else if (!strcmp(sub->name, "default")) {
4923 GETVAL(value, sub, "value");
4924
Radek Krejciac1a52c2016-09-15 14:42:40 +02004925 /* check for duplicity in case of configuration data,
4926 * in case of status data duplicities are allowed */
4927 if (llist->flags & LYS_CONFIG_W) {
4928 for (r = 0; r < llist->dflt_size; r++) {
4929 if (ly_strequal(llist->dflt[r], value, 1)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004930 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, "default");
Michal Vasko51e5c582017-01-19 14:16:39 +01004931 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "Duplicated default value \"%s\".", value);
Radek Krejciac1a52c2016-09-15 14:42:40 +02004932 goto error;
4933 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004934 }
4935 }
4936 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004937 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004938 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004939
Radek Krejcicbb473e2016-09-16 14:48:32 +02004940 /* finalize type parsing */
4941 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
4942 llist->type.der = NULL;
4943 goto error;
4944 }
4945
Radek Krejcid5a5c282016-08-15 15:38:08 +02004946 if (llist->dflt_size && llist->min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004947 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "min-elements", "leaf-list");
Michal Vasko51e5c582017-01-19 14:16:39 +01004948 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02004949 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
4950 goto error;
4951 }
4952
4953 /* check default value (if not defined, there still could be some restrictions
4954 * that need to be checked against a default value from a derived type) */
4955 for (r = 0; r < llist->dflt_size; r++) {
Radek Krejci51673202016-11-01 17:00:32 +01004956 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
4957 (struct lys_node *)(&llist->dflt[r])) == -1) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02004958 goto error;
Radek Krejci25d782a2015-05-22 15:03:23 +02004959 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004960 }
4961
Michal Vasko508a50d2016-09-07 14:50:33 +02004962 /* check XPath dependencies */
4963 if ((llist->when || llist->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4964 goto error;
4965 }
4966
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004967 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004968
4969error:
4970
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004971 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004972
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004973 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004974}
4975
Michal Vasko0d343d12015-08-24 14:57:36 +02004976/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004977static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004978read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004979 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004980{
Radek Krejci1d82ef62015-08-07 14:44:40 +02004981 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02004982 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004983 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01004984 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01004985 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004986 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejci5c08a992016-11-02 13:30:04 +01004987 const char *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004988 char *auxs;
4989 unsigned long val;
Radek Krejcie36d7c72017-01-17 16:12:30 +01004990 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004991
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004992 /* init */
4993 memset(&root, 0, sizeof root);
4994 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02004995
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004996 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01004997 if (!list) {
4998 LOGMEM;
4999 return NULL;
5000 }
Radek Krejci76512572015-08-04 09:47:08 +02005001 list->nodetype = LYS_LIST;
5002 list->prev = (struct lys_node *)list;
5003 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005004
Radek Krejci07d0fb92017-01-13 14:11:05 +01005005 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
5006 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005007 goto error;
5008 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005009
Radek Krejcia9544502015-08-14 08:24:29 +02005010 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5011
Radek Krejcic189a952016-07-11 15:27:07 +02005012 /* insert the node into the schema tree */
5013 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5014 goto error;
5015 }
5016
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005017 /* process list's specific children */
5018 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005019 if (strcmp(sub->ns->value, LY_NSYIN)) {
5020 /* extension */
5021 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005022 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02005023
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005024 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005025 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005026 !strcmp(sub->name, "leaf-list") ||
5027 !strcmp(sub->name, "leaf") ||
5028 !strcmp(sub->name, "list") ||
5029 !strcmp(sub->name, "choice") ||
5030 !strcmp(sub->name, "uses") ||
5031 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005032 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005033 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005034 !strcmp(sub->name, "action") ||
5035 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005036 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005037 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005038
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005039 /* array counters */
5040 } else if (!strcmp(sub->name, "key")) {
5041 /* check cardinality 0..1 */
5042 if (list->keys_size) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005043 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005044 goto error;
5045 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005046
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005047 /* count the number of keys */
5048 GETVAL(value, sub, "value");
Radek Krejci5c08a992016-11-02 13:30:04 +01005049 list->keys_str = lydict_insert(module->ctx, value, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005050 while ((value = strpbrk(value, " \t\n"))) {
5051 list->keys_size++;
5052 while (isspace(*value)) {
5053 value++;
5054 }
5055 }
5056 list->keys_size++;
5057 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01005058 if (!list->keys) {
5059 LOGMEM;
5060 goto error;
5061 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005062
Radek Krejci8d6b7422017-02-03 14:42:13 +01005063 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_KEY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005064 goto error;
5065 }
5066 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005067 } else if (!strcmp(sub->name, "unique")) {
5068 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005069 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005070 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005071 } else if (!strcmp(sub->name, "typedef")) {
5072 c_tpdf++;
5073 } else if (!strcmp(sub->name, "must")) {
5074 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005075 } else if (!strcmp(sub->name, "if-feature")) {
5076 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02005077
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005078 /* optional stetments */
5079 } else if (!strcmp(sub->name, "ordered-by")) {
5080 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005081 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005082 goto error;
5083 }
5084 /* just checking the flags in llist is not sufficient, we would
5085 * allow multiple ordered-by statements with the "system" value
5086 */
5087 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005088
Radek Krejci1574a8d2015-08-03 14:16:52 +02005089 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005090 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
5091 * state data
5092 */
Michal Vasko345da0a2015-12-02 10:35:55 +01005093 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005094 continue;
5095 }
Radek Krejci345ad742015-06-03 11:04:18 +02005096
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005097 GETVAL(value, sub, "value");
5098 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02005099 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005100 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005101 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005102 goto error;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005103 } /* else system is the default value, so we can ignore it */
5104
Radek Krejci8d6b7422017-02-03 14:42:13 +01005105 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005106 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005107 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005108 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005109 } else if (!strcmp(sub->name, "min-elements")) {
5110 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005111 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005112 goto error;
5113 }
5114 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005115
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005116 GETVAL(value, sub, "value");
5117 while (isspace(value[0])) {
5118 value++;
5119 }
Radek Krejci345ad742015-06-03 11:04:18 +02005120
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005121 /* convert it to uint32_t */
5122 errno = 0;
5123 auxs = NULL;
5124 val = strtoul(value, &auxs, 10);
5125 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005126 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005127 goto error;
5128 }
5129 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005130 if (list->max && (list->min > list->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005131 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01005132 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005133 lyxml_free(module->ctx, sub);
5134 goto error;
5135 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005136 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005137 goto error;
5138 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005139 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005140 } else if (!strcmp(sub->name, "max-elements")) {
5141 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005142 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005143 goto error;
5144 }
5145 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005146
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005147 GETVAL(value, sub, "value");
5148 while (isspace(value[0])) {
5149 value++;
5150 }
Radek Krejci345ad742015-06-03 11:04:18 +02005151
Radek Krejci0d7b2472016-02-12 11:11:03 +01005152 if (!strcmp(value, "unbounded")) {
5153 list->max = 0;;
5154 } else {
5155 /* convert it to uint32_t */
5156 errno = 0;
5157 auxs = NULL;
5158 val = strtoul(value, &auxs, 10);
5159 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005160 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01005161 goto error;
5162 }
5163 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005164 if (list->min > list->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005165 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01005166 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005167 goto error;
5168 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005169 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005170 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005171 goto error;
5172 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005173 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005174 } else if (!strcmp(sub->name, "when")) {
5175 if (list->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005176 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005177 goto error;
5178 }
5179
Radek Krejci5323b492017-01-16 15:40:11 +01005180 list->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005181 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005182 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005183 goto error;
5184 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005185 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005186 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005187 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005188 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005189 }
5190 }
Radek Krejci345ad742015-06-03 11:04:18 +02005191
Michal Vaskoe022a562016-09-27 14:24:15 +02005192 /* check - if list is configuration, key statement is mandatory
5193 * (but only if we are not in a grouping or augment, then the check is deferred) */
Radek Krejcif95b6292017-02-13 15:57:37 +01005194 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); node = node->parent);
Radek Krejci5c08a992016-11-02 13:30:04 +01005195 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys_str) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005196 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005197 goto error;
5198 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005199
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005200 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5201 if (c_tpdf) {
5202 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005203 if (!list->tpdf) {
5204 LOGMEM;
5205 goto error;
5206 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005207 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005208 if (c_must) {
5209 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01005210 if (!list->must) {
5211 LOGMEM;
5212 goto error;
5213 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005214 }
5215 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005216 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
5217 if (!list->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005218 LOGMEM;
5219 goto error;
5220 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005221 }
Radek Krejcie534c132016-11-23 13:32:31 +01005222 if (c_ext) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005223 /* some extensions may be already present from the substatements */
5224 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5225 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005226 LOGMEM;
5227 goto error;
5228 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005229 retval->ext = reallocated;
5230
5231 /* init memory */
5232 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005233 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005234
Radek Krejcie534c132016-11-23 13:32:31 +01005235 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5236 if (strcmp(sub->ns->value, LY_NSYIN)) {
5237 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005238 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 +01005239 retval->ext_size++;
5240 if (r) {
5241 goto error;
5242 }
5243 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005244 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
5245 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005246 if (r) {
5247 goto error;
5248 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005249 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005250 r = fill_yin_iffeature(retval, 0, sub, &list->iffeature[list->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005251 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005252 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005253 goto error;
5254 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005255 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005256 r = fill_yin_must(module, sub, &list->must[list->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005257 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005258 if (r) {
5259 goto error;
5260 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005261 }
5262 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005263
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005264 /* last part - process data nodes */
5265 LY_TREE_FOR_SAFE(root.child, next, sub) {
5266 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005267 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005268 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005269 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005270 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005271 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005272 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005273 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005274 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005275 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005276 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005277 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005278 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005279 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005280 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005281 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005282 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005283 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005284 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005285 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005286 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005287 node = read_yin_notif(module, retval, sub, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005288 } else {
5289 LOGINT;
5290 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005291 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005292 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005293 goto error;
5294 }
Radek Krejci73adb602015-07-02 18:07:40 +02005295
Michal Vasko345da0a2015-12-02 10:35:55 +01005296 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005297 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005298
Radek Krejci5c08a992016-11-02 13:30:04 +01005299 if (list->keys_str) {
5300 /* check that we are not in grouping */
5301 for (node = parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
5302 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01005303 goto error;
5304 }
5305 } /* 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 +02005306
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005307 /* process unique statements */
5308 if (c_uniq) {
5309 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01005310 if (!list->unique) {
5311 LOGMEM;
5312 goto error;
5313 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005314
Radek Krejci461efb92016-02-12 15:52:18 +01005315 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
5316 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
5317 list->unique_size++;
5318 if (r) {
5319 goto error;
5320 }
5321
Radek Krejci8d6b7422017-02-03 14:42:13 +01005322 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub,
Radek Krejcie36d7c72017-01-17 16:12:30 +01005323 LYEXT_SUBSTMT_UNIQUE, list->unique_size - 1, unres)) {
5324 goto error;
5325 }
Radek Krejci461efb92016-02-12 15:52:18 +01005326 lyxml_free(module->ctx, sub);
5327 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005328 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005329
Michal Vasko508a50d2016-09-07 14:50:33 +02005330 /* check XPath dependencies */
5331 if ((list->when || list->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5332 goto error;
5333 }
5334
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005335 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005336
5337error:
5338
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005339 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005340 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005341 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005342 }
5343 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005344 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005345 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005346
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005347 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005348}
5349
Michal Vasko0d343d12015-08-24 14:57:36 +02005350/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005351static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005352read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02005353 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005354{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005355 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005356 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005357 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005358 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005359 const char *value;
Radek Krejci07d0fb92017-01-13 14:11:05 +01005360 void *reallocated;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005361 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005362 int c_tpdf = 0, c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005363
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005364 /* init */
5365 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005366
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005367 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01005368 if (!cont) {
5369 LOGMEM;
5370 return NULL;
5371 }
Radek Krejci76512572015-08-04 09:47:08 +02005372 cont->nodetype = LYS_CONTAINER;
5373 cont->prev = (struct lys_node *)cont;
5374 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005375
Radek Krejci07d0fb92017-01-13 14:11:05 +01005376 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
5377 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005378 goto error;
5379 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005380
Radek Krejcia9544502015-08-14 08:24:29 +02005381 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5382
Radek Krejcic189a952016-07-11 15:27:07 +02005383 /* insert the node into the schema tree */
5384 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5385 goto error;
5386 }
5387
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005388 /* process container's specific children */
5389 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005390 if (strcmp(sub->ns->value, LY_NSYIN)) {
5391 /* extension */
5392 c_ext++;
5393 } else if (!strcmp(sub->name, "presence")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005394 if (cont->presence) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005395 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005396 goto error;
5397 }
5398 GETVAL(value, sub, "value");
5399 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02005400
Radek Krejci8d6b7422017-02-03 14:42:13 +01005401 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005402 goto error;
5403 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005404 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005405 } else if (!strcmp(sub->name, "when")) {
5406 if (cont->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005407 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005408 goto error;
5409 }
5410
Radek Krejci5323b492017-01-16 15:40:11 +01005411 cont->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005412 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005413 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005414 goto error;
5415 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005416 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02005417
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005418 /* data statements */
5419 } else if (!strcmp(sub->name, "container") ||
5420 !strcmp(sub->name, "leaf-list") ||
5421 !strcmp(sub->name, "leaf") ||
5422 !strcmp(sub->name, "list") ||
5423 !strcmp(sub->name, "choice") ||
5424 !strcmp(sub->name, "uses") ||
5425 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005426 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005427 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005428 !strcmp(sub->name, "action") ||
5429 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005430 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005431 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005432
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005433 /* array counters */
5434 } else if (!strcmp(sub->name, "typedef")) {
5435 c_tpdf++;
5436 } else if (!strcmp(sub->name, "must")) {
5437 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005438 } else if (!strcmp(sub->name, "if-feature")) {
5439 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005440 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005441 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005442 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005443 }
5444 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005445
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005446 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5447 if (c_tpdf) {
5448 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005449 if (!cont->tpdf) {
5450 LOGMEM;
5451 goto error;
5452 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005453 }
5454 if (c_must) {
5455 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01005456 if (!cont->must) {
5457 LOGMEM;
5458 goto error;
5459 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005460 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005461 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005462 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
5463 if (!cont->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005464 LOGMEM;
5465 goto error;
5466 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005467 }
Radek Krejcie534c132016-11-23 13:32:31 +01005468 if (c_ext) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01005469 /* some extensions may be already present from the substatements */
5470 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5471 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005472 LOGMEM;
5473 goto error;
5474 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01005475 retval->ext = reallocated;
5476
5477 /* init memory */
5478 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005479 }
Radek Krejci800af702015-06-02 13:46:01 +02005480
Radek Krejcie534c132016-11-23 13:32:31 +01005481 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5482 if (strcmp(sub->ns->value, LY_NSYIN)) {
5483 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005484 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 +01005485 retval->ext_size++;
5486 if (r) {
5487 goto error;
5488 }
5489 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005490 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
5491 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005492 if (r) {
5493 goto error;
5494 }
5495 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005496 r = fill_yin_must(module, sub, &cont->must[cont->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005497 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005498 if (r) {
5499 goto error;
5500 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005501 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005502 r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005503 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005504 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005505 goto error;
5506 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005507 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005508 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005509
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005510 /* last part - process data nodes */
5511 LY_TREE_FOR_SAFE(root.child, next, sub) {
5512 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005513 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005514 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005515 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005516 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005517 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005518 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005519 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005520 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005521 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005522 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005523 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005524 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005525 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005526 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005527 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005528 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005529 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005530 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005531 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005532 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005533 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005534 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005535 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005536 goto error;
5537 }
Radek Krejci73adb602015-07-02 18:07:40 +02005538
Michal Vasko345da0a2015-12-02 10:35:55 +01005539 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005540 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005541
Michal Vasko508a50d2016-09-07 14:50:33 +02005542 /* check XPath dependencies */
5543 if ((cont->when || cont->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5544 goto error;
5545 }
5546
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005547 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005548
5549error:
5550
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005551 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005552 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005553 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005554 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005555
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005556 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005557}
5558
Michal Vasko0d343d12015-08-24 14:57:36 +02005559/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005560static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005561read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02005562 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005563{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005564 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005565 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005566 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005567 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005568 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005569 int c_tpdf = 0, c_ext = 0;
Radek Krejcifdc0d702017-01-23 15:58:38 +01005570 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005571
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005572 /* init */
5573 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005574
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005575 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01005576 if (!grp) {
5577 LOGMEM;
5578 return NULL;
5579 }
Radek Krejci76512572015-08-04 09:47:08 +02005580 grp->nodetype = LYS_GROUPING;
5581 grp->prev = (struct lys_node *)grp;
5582 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005583
Radek Krejci07d0fb92017-01-13 14:11:05 +01005584 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE , unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005585 goto error;
5586 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005587
Radek Krejcia9544502015-08-14 08:24:29 +02005588 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5589
Radek Krejcic189a952016-07-11 15:27:07 +02005590 /* insert the node into the schema tree */
5591 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5592 goto error;
5593 }
5594
Radek Krejci1d82ef62015-08-07 14:44:40 +02005595 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005596 if (strcmp(sub->ns->value, LY_NSYIN)) {
5597 /* extension */
5598 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005599
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005600 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005601 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005602 !strcmp(sub->name, "leaf-list") ||
5603 !strcmp(sub->name, "leaf") ||
5604 !strcmp(sub->name, "list") ||
5605 !strcmp(sub->name, "choice") ||
5606 !strcmp(sub->name, "uses") ||
5607 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005608 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005609 !strcmp(sub->name, "anydata") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02005610 !strcmp(sub->name, "action") ||
5611 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005612 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005613 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005614
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005615 /* array counters */
5616 } else if (!strcmp(sub->name, "typedef")) {
5617 c_tpdf++;
5618 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005619 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005620 goto error;
5621 }
5622 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005623
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005624 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5625 if (c_tpdf) {
5626 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005627 if (!grp->tpdf) {
5628 LOGMEM;
5629 goto error;
5630 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005631 }
Radek Krejcie534c132016-11-23 13:32:31 +01005632 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01005633 /* some extensions may be already present from the substatements */
5634 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5635 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005636 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02005637 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005638 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01005639 retval->ext = reallocated;
5640
5641 /* init memory */
5642 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005643 }
Radek Krejcie534c132016-11-23 13:32:31 +01005644 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5645 if (strcmp(sub->ns->value, LY_NSYIN)) {
5646 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005647 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 +01005648 retval->ext_size++;
5649 if (r) {
5650 goto error;
5651 }
5652 } else {
5653 /* typedef */
5654 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
5655 grp->tpdf_size++;
5656 if (r) {
5657 goto error;
5658 }
5659 }
5660 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005661
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005662 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02005663 if (!root.child) {
5664 LOGWRN("Grouping \"%s\" without children.", retval->name);
5665 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005666 LY_TREE_FOR_SAFE(root.child, next, sub) {
5667 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005668 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005669 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005670 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005671 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005672 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005673 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005674 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005675 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005676 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005677 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005678 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005679 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005680 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005681 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005682 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005683 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005684 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005685 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005686 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02005687 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005688 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005689 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005690 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005691 goto error;
5692 }
Radek Krejci73adb602015-07-02 18:07:40 +02005693
Michal Vasko345da0a2015-12-02 10:35:55 +01005694 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005695 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005696
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005697 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005698
5699error:
5700
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005701 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005702 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005703 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005704 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005705
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005706 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005707}
5708
Michal Vasko0d343d12015-08-24 14:57:36 +02005709/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005710static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005711read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02005712 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005713{
Radek Krejcie0674f82015-06-15 13:58:51 +02005714 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005715 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02005716 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02005717 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005718 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005719 int c_tpdf = 0, c_must = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005720
Radek Krejcie0674f82015-06-15 13:58:51 +02005721 /* init */
5722 memset(&root, 0, sizeof root);
5723
Michal Vasko38d01f72015-06-15 09:41:06 +02005724 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01005725 if (!inout) {
5726 LOGMEM;
5727 return NULL;
5728 }
Radek Krejci6acc8012015-08-13 09:07:04 +02005729 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005730
5731 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02005732 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005733 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005734 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02005735 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005736 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005737 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02005738 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02005739 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02005740 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005741 }
5742
Radek Krejci76512572015-08-04 09:47:08 +02005743 retval = (struct lys_node *)inout;
Radek Krejcie7770892017-01-24 13:18:01 +01005744 retval->module = module;
Michal Vaskoebeac942015-06-15 12:11:50 +02005745
Radek Krejcia9544502015-08-14 08:24:29 +02005746 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5747
Radek Krejcic189a952016-07-11 15:27:07 +02005748 /* insert the node into the schema tree */
5749 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5750 goto error;
5751 }
5752
Michal Vasko38d01f72015-06-15 09:41:06 +02005753 /* data statements */
5754 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie7770892017-01-24 13:18:01 +01005755 if (!sub->ns) {
5756 /* garbage */
5757 lyxml_free(module->ctx, sub);
5758 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01005759 /* extension */
5760 c_ext++;
5761 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005762 !strcmp(sub->name, "leaf-list") ||
5763 !strcmp(sub->name, "leaf") ||
5764 !strcmp(sub->name, "list") ||
5765 !strcmp(sub->name, "choice") ||
5766 !strcmp(sub->name, "uses") ||
5767 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005768 !strcmp(sub->name, "anyxml") ||
5769 !strcmp(sub->name, "anydata")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005770 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005771 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005772
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005773 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005774 } else if (!strcmp(sub->name, "typedef")) {
5775 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02005776
Radek Krejci1a31efe2016-07-29 11:04:16 +02005777 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005778 c_must++;
5779
Michal Vasko38d01f72015-06-15 09:41:06 +02005780 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005781 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005782 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005783 }
5784 }
5785
5786 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5787 if (c_tpdf) {
5788 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005789 if (!inout->tpdf) {
5790 LOGMEM;
5791 goto error;
5792 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005793 }
Radek Krejci19332802016-07-29 10:39:46 +02005794 if (c_must) {
5795 inout->must = calloc(c_must, sizeof *inout->must);
5796 if (!inout->must) {
5797 LOGMEM;
5798 goto error;
5799 }
5800 }
Radek Krejcie534c132016-11-23 13:32:31 +01005801 if (c_ext) {
5802 inout->ext = calloc(c_ext, sizeof *inout->ext);
5803 if (!inout->ext) {
5804 LOGMEM;
5805 goto error;
5806 }
5807 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005808
Radek Krejcie534c132016-11-23 13:32:31 +01005809 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5810 if (strcmp(sub->ns->value, LY_NSYIN)) {
5811 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005812 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 +01005813 retval->ext_size++;
5814 if (r) {
5815 goto error;
5816 }
5817 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005818 r = fill_yin_must(module, sub, &inout->must[inout->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02005819 inout->must_size++;
5820 if (r) {
5821 goto error;
5822 }
5823 } else { /* typedef */
5824 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
5825 inout->tpdf_size++;
5826 if (r) {
5827 goto error;
5828 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005829 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005830 }
5831
5832 /* last part - process data nodes */
5833 LY_TREE_FOR_SAFE(root.child, next, sub) {
5834 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005835 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005836 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005837 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005838 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005839 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005840 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005841 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005842 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005843 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005844 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005845 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005846 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005847 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005848 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005849 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005850 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005851 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005852 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005853 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005854 goto error;
5855 }
Radek Krejci73adb602015-07-02 18:07:40 +02005856
Michal Vasko345da0a2015-12-02 10:35:55 +01005857 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005858 }
5859
Michal Vasko508a50d2016-09-07 14:50:33 +02005860 /* check XPath dependencies */
5861 if (inout->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5862 goto error;
5863 }
5864
Michal Vasko38d01f72015-06-15 09:41:06 +02005865 return retval;
5866
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005867error:
Michal Vasko38d01f72015-06-15 09:41:06 +02005868
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005869 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02005870 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005871 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005872 }
5873
5874 return NULL;
5875}
5876
Michal Vasko0d343d12015-08-24 14:57:36 +02005877/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005878static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005879read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02005880 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02005881{
Michal Vaskoc6551b32015-06-16 10:51:43 +02005882 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005883 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005884 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005885 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005886 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005887 int c_tpdf = 0, c_ftrs = 0, c_must = 0, c_ext = 0;
Radek Krejci478ef1d2017-01-24 13:56:09 +01005888 void *reallocated;
Michal Vasko0ea41032015-06-16 08:53:55 +02005889
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005890 if (parent && (module->version < 2)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005891 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "notification");
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005892 return NULL;
5893 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005894
Michal Vaskoc6551b32015-06-16 10:51:43 +02005895 memset(&root, 0, sizeof root);
5896
Michal Vasko0ea41032015-06-16 08:53:55 +02005897 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01005898 if (!notif) {
5899 LOGMEM;
5900 return NULL;
5901 }
Radek Krejci76512572015-08-04 09:47:08 +02005902 notif->nodetype = LYS_NOTIF;
5903 notif->prev = (struct lys_node *)notif;
5904 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005905
Radek Krejci07d0fb92017-01-13 14:11:05 +01005906 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005907 goto error;
5908 }
5909
Radek Krejcia9544502015-08-14 08:24:29 +02005910 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5911
Radek Krejcic189a952016-07-11 15:27:07 +02005912 /* insert the node into the schema tree */
5913 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5914 goto error;
5915 }
5916
Michal Vasko0ea41032015-06-16 08:53:55 +02005917 /* process rpc's specific children */
5918 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005919 if (strcmp(sub->ns->value, LY_NSYIN)) {
5920 /* extension */
5921 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005922 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02005923
Michal Vasko0ea41032015-06-16 08:53:55 +02005924 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005925 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005926 !strcmp(sub->name, "leaf-list") ||
5927 !strcmp(sub->name, "leaf") ||
5928 !strcmp(sub->name, "list") ||
5929 !strcmp(sub->name, "choice") ||
5930 !strcmp(sub->name, "uses") ||
5931 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005932 !strcmp(sub->name, "anyxml") ||
5933 !strcmp(sub->name, "anydata")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005934 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005935 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02005936
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005937 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02005938 } else if (!strcmp(sub->name, "typedef")) {
5939 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005940 } else if (!strcmp(sub->name, "if-feature")) {
5941 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02005942 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005943 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02005944 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005945 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02005946 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02005947 }
5948 }
5949
5950 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5951 if (c_tpdf) {
5952 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005953 if (!notif->tpdf) {
5954 LOGMEM;
5955 goto error;
5956 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005957 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005958 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005959 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
5960 if (!notif->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005961 LOGMEM;
5962 goto error;
5963 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005964 }
Radek Krejci19332802016-07-29 10:39:46 +02005965 if (c_must) {
5966 notif->must = calloc(c_must, sizeof *notif->must);
5967 if (!notif->must) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005968 LOGMEM;
5969 goto error;
5970 }
5971 }
Radek Krejcie534c132016-11-23 13:32:31 +01005972 if (c_ext) {
Radek Krejci478ef1d2017-01-24 13:56:09 +01005973 /* some extensions may be already present from the substatements */
5974 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5975 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005976 LOGMEM;
5977 goto error;
5978 }
Radek Krejci478ef1d2017-01-24 13:56:09 +01005979 retval->ext = reallocated;
5980
5981 /* init memory */
5982 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005983 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005984
Radek Krejcie534c132016-11-23 13:32:31 +01005985 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5986 if (strcmp(sub->ns->value, LY_NSYIN)) {
5987 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005988 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 +01005989 retval->ext_size++;
5990 if (r) {
5991 goto error;
5992 }
5993 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005994 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
5995 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02005996 if (r) {
5997 goto error;
5998 }
Radek Krejci96299152016-06-22 10:17:50 +02005999 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006000 r = fill_yin_iffeature(retval, 0, sub, &notif->iffeature[notif->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006001 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006002 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006003 goto error;
6004 }
Radek Krejci19332802016-07-29 10:39:46 +02006005 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01006006 r = fill_yin_must(module, sub, &notif->must[notif->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02006007 notif->must_size++;
Radek Krejci0b24d752015-07-02 15:02:27 +02006008 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006009 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006010 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006011 }
Michal Vasko0ea41032015-06-16 08:53:55 +02006012 }
6013
6014 /* last part - process data nodes */
6015 LY_TREE_FOR_SAFE(root.child, next, sub) {
6016 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006017 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006018 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006019 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006020 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006021 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006022 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006023 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006024 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006025 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006026 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02006027 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006028 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006029 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006030 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006031 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02006032 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006033 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02006034 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006035 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02006036 goto error;
6037 }
Radek Krejci73adb602015-07-02 18:07:40 +02006038
Michal Vasko345da0a2015-12-02 10:35:55 +01006039 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02006040 }
6041
Michal Vasko508a50d2016-09-07 14:50:33 +02006042 /* check XPath dependencies */
6043 if (notif->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
6044 goto error;
6045 }
6046
Michal Vasko0ea41032015-06-16 08:53:55 +02006047 return retval;
6048
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006049error:
Michal Vasko0ea41032015-06-16 08:53:55 +02006050
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006051 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02006052 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006053 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02006054 }
6055
6056 return NULL;
6057}
6058
Michal Vasko0d343d12015-08-24 14:57:36 +02006059/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02006060static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02006061read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006062 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02006063{
Radek Krejcie0674f82015-06-15 13:58:51 +02006064 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006065 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02006066 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02006067 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006068 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01006069 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0, c_ext = 0;
Radek Krejci94596cf2017-01-24 13:19:16 +01006070 void *reallocated;
Michal Vasko38d01f72015-06-15 09:41:06 +02006071
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006072 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006073 if (module->version < 2) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006074 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "action");
Michal Vaskobb174852016-07-25 11:00:21 +02006075 return NULL;
6076 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006077 for (node = parent; node; node = lys_parent(node)) {
Radek Krejcia3b19f72016-09-30 13:02:45 +02006078 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006079 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006080 LOGVAL(LYE_INPAR, LY_VLOG_LYS, parent, strnodetype(node->nodetype), "action");
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006081 return NULL;
6082 }
6083 }
6084 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006085
Radek Krejcie0674f82015-06-15 13:58:51 +02006086 /* init */
6087 memset(&root, 0, sizeof root);
6088
Michal Vasko38d01f72015-06-15 09:41:06 +02006089 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01006090 if (!rpc) {
6091 LOGMEM;
6092 return NULL;
6093 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006094 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02006095 rpc->prev = (struct lys_node *)rpc;
6096 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006097
Radek Krejci07d0fb92017-01-13 14:11:05 +01006098 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006099 goto error;
6100 }
6101
Radek Krejcia9544502015-08-14 08:24:29 +02006102 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
6103
Radek Krejcic189a952016-07-11 15:27:07 +02006104 /* insert the node into the schema tree */
6105 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6106 goto error;
6107 }
6108
Michal Vasko38d01f72015-06-15 09:41:06 +02006109 /* process rpc's specific children */
6110 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006111 if (strcmp(sub->ns->value, LY_NSYIN)) {
6112 /* extension */
6113 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006114 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006115 } else if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006116 if (c_input) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006117 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006118 goto error;
6119 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006120 c_input++;
Michal Vaskof3930de2015-10-22 12:03:59 +02006121 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006122 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006123 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006124 if (c_output) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006125 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006126 goto error;
6127 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006128 c_output++;
Michal Vaskof3930de2015-10-22 12:03:59 +02006129 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006130 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006131
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006132 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02006133 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02006134 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006135 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006136
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006137 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02006138 } else if (!strcmp(sub->name, "typedef")) {
6139 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006140 } else if (!strcmp(sub->name, "if-feature")) {
6141 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006142 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006143 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006144 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02006145 }
6146 }
6147
6148 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6149 if (c_tpdf) {
6150 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01006151 if (!rpc->tpdf) {
6152 LOGMEM;
6153 goto error;
6154 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006155 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006156 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006157 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
6158 if (!rpc->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01006159 LOGMEM;
6160 goto error;
6161 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006162 }
Radek Krejcie534c132016-11-23 13:32:31 +01006163 if (c_ext) {
Radek Krejci94596cf2017-01-24 13:19:16 +01006164 /* some extensions may be already present from the substatements */
6165 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
6166 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01006167 LOGMEM;
6168 goto error;
6169 }
Radek Krejci94596cf2017-01-24 13:19:16 +01006170 retval->ext = reallocated;
6171
6172 /* init memory */
6173 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006174 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006175
Radek Krejcie534c132016-11-23 13:32:31 +01006176 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6177 if (strcmp(sub->ns->value, LY_NSYIN)) {
6178 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006179 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 +01006180 retval->ext_size++;
6181 if (r) {
6182 goto error;
6183 }
6184 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006185 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
6186 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006187 if (r) {
6188 goto error;
6189 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006190 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006191 r = fill_yin_iffeature(retval, 0, sub, &rpc->iffeature[rpc->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006192 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006193 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006194 goto error;
6195 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006196 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006197 }
6198
6199 /* last part - process data nodes */
6200 LY_TREE_FOR_SAFE(root.child, next, sub) {
6201 if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006202 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006203 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006204 node = read_yin_input_output(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006205 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006206 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006207 goto error;
6208 }
Radek Krejci73adb602015-07-02 18:07:40 +02006209
Michal Vasko345da0a2015-12-02 10:35:55 +01006210 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006211 }
6212
Michal Vasko38d01f72015-06-15 09:41:06 +02006213 return retval;
6214
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006215error:
Michal Vasko38d01f72015-06-15 09:41:06 +02006216
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006217 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006218 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006219 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006220 }
6221
6222 return NULL;
6223}
6224
Michal Vasko0d343d12015-08-24 14:57:36 +02006225/* logs directly
6226 *
Radek Krejci74705112015-06-05 10:25:44 +02006227 * resolve - referenced grouping should be bounded to the namespace (resolved)
6228 * only when uses does not appear in grouping. In a case of grouping's uses,
6229 * we just get information but we do not apply augment or refine to it.
6230 */
Radek Krejci76512572015-08-04 09:47:08 +02006231static struct lys_node *
Radek Krejci3440cc52016-06-23 17:03:59 +02006232read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02006233{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006234 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02006235 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006236 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006237 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01006238 int c_ref = 0, c_aug = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006239 int r;
Radek Krejcifdc0d702017-01-23 15:58:38 +01006240 void *reallocated;
Radek Krejci74705112015-06-05 10:25:44 +02006241
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006242 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01006243 if (!uses) {
6244 LOGMEM;
6245 return NULL;
6246 }
Radek Krejci76512572015-08-04 09:47:08 +02006247 uses->nodetype = LYS_USES;
6248 uses->prev = (struct lys_node *)uses;
6249 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02006250
Radek Krejcia9544502015-08-14 08:24:29 +02006251 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006252 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02006253
Radek Krejci07d0fb92017-01-13 14:11:05 +01006254 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006255 goto error;
6256 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006257
Radek Krejcia9544502015-08-14 08:24:29 +02006258 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
6259
Radek Krejcic189a952016-07-11 15:27:07 +02006260 /* insert the node into the schema tree */
6261 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6262 goto error;
6263 }
6264
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006265 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02006266 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006267 if (strcmp(sub->ns->value, LY_NSYIN)) {
6268 /* extension */
6269 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006270 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006271 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006272 c_ref++;
6273 } else if (!strcmp(sub->name, "augment")) {
6274 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006275 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02006276 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006277 } else if (!strcmp(sub->name, "when")) {
6278 if (uses->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006279 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006280 goto error;
6281 }
6282
Radek Krejci5323b492017-01-16 15:40:11 +01006283 uses->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006284 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006285 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006286 goto error;
6287 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006288 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006289 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006290 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006291 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006292 }
6293 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006294
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006295 /* process properties with cardinality 0..n */
6296 if (c_ref) {
6297 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01006298 if (!uses->refine) {
6299 LOGMEM;
6300 goto error;
6301 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006302 }
6303 if (c_aug) {
6304 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01006305 if (!uses->augment) {
6306 LOGMEM;
6307 goto error;
6308 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006309 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006310 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006311 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
6312 if (!uses->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01006313 LOGMEM;
6314 goto error;
6315 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006316 }
Radek Krejcie534c132016-11-23 13:32:31 +01006317 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01006318 /* some extensions may be already present from the substatements */
6319 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
6320 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01006321 LOGMEM;
6322 goto error;
6323 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01006324 retval->ext = reallocated;
6325
6326 /* init memory */
6327 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006328 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006329
Radek Krejcie534c132016-11-23 13:32:31 +01006330 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6331 if (strcmp(sub->ns->value, LY_NSYIN)) {
6332 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006333 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 +01006334 retval->ext_size++;
6335 if (r) {
6336 goto error;
6337 }
6338 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02006339 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006340 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006341 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006342 goto error;
6343 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006344 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006345 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
6346 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006347 if (r) {
6348 goto error;
6349 }
6350 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006351 r = fill_yin_iffeature(retval, 0, sub, &uses->iffeature[uses->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006352 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006353 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006354 goto error;
6355 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006356 }
6357 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006358
Radek Krejci48464ed2016-03-17 15:44:09 +01006359 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006360 goto error;
6361 }
Radek Krejci74705112015-06-05 10:25:44 +02006362
Michal Vasko508a50d2016-09-07 14:50:33 +02006363 /* check XPath dependencies */
6364 if (uses->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
6365 goto error;
6366 }
6367
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006368 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006369
6370error:
6371
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006372 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006373
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006374 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006375}
6376
Michal Vasko0d343d12015-08-24 14:57:36 +02006377/* logs directly
6378 *
6379 * common code for yin_read_module() and yin_read_submodule()
6380 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006381static int
Radek Krejcic071c542016-01-27 14:57:51 +01006382read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
6383 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02006384{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006385 struct ly_ctx *ctx = module->ctx;
Radek Krejci7417a082017-02-16 11:07:59 +01006386 struct lyxml_elem *next, *child, root, grps, augs, revs, exts;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006387 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006388 struct lys_module *trg;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006389 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01006390 int i, r, ret = -1;
Radek Krejcic071c542016-01-27 14:57:51 +01006391 int version_flag = 0;
Michal Vasko5de8a022017-02-08 10:57:26 +01006392 /* (sub)module substatements are ordered in groups, increment this value when moving to another group
6393 * 0 - header-stmts, 1 - linkage-stmts, 2 - meta-stmts, 3 - revision-stmts, 4 - body-stmts */
6394 int substmt_group;
6395 /* just remember last substatement for logging */
6396 const char *substmt_prev;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006397 /* counters */
Radek Krejcie534c132016-11-23 13:32:31 +01006398 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;
6399 int c_ext = 0, c_extinst = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01006400 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006401
Radek Krejcic071c542016-01-27 14:57:51 +01006402 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02006403 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01006404
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006405 /* init */
6406 memset(&root, 0, sizeof root);
6407 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006408 memset(&augs, 0, sizeof augs);
Radek Krejcie534c132016-11-23 13:32:31 +01006409 memset(&exts, 0, sizeof exts);
PavolVican9e81c6a2017-02-09 13:09:07 +01006410 memset(&revs, 0, sizeof revs);
Radek Krejcie0674f82015-06-15 13:58:51 +02006411
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006412 /*
6413 * in the first run, we process elements with cardinality of 1 or 0..1 and
6414 * count elements with cardinality 0..n. Data elements (choices, containers,
6415 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
6416 * need have all top-level and groupings already prepared at that time. In
6417 * the middle loop, we process other elements with carinality of 0..n since
6418 * we need to allocate arrays to store them.
6419 */
Michal Vasko5de8a022017-02-08 10:57:26 +01006420 substmt_group = 0;
6421 substmt_prev = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006422 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01006423 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02006424 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01006425 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006426 continue;
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006427 } else if (strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01006428 /* possible extension instance */
6429 lyxml_unlink_elem(module->ctx, child, 2);
6430 lyxml_add_child(module->ctx, &exts, child);
6431 c_extinst++;
6432 } else if (!submodule && !strcmp(child->name, "namespace")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006433 if (substmt_group > 0) {
6434 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6435 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6436 child->name, substmt_prev);
6437 goto error;
6438 }
6439
PavolVican9e81c6a2017-02-09 13:09:07 +01006440 if (trg->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006441 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006442 goto error;
6443 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006444 GETVAL(value, child, "uri");
PavolVican9e81c6a2017-02-09 13:09:07 +01006445 trg->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006446
Radek Krejci8d6b7422017-02-03 14:42:13 +01006447 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_NAMESPACE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006448 goto error;
6449 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006450 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006451
6452 substmt_prev = "namespace";
Radek Krejcic071c542016-01-27 14:57:51 +01006453 } else if (!submodule && !strcmp(child->name, "prefix")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006454 if (substmt_group > 0) {
6455 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6456 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6457 child->name, substmt_prev);
6458 goto error;
6459 }
6460
PavolVican9e81c6a2017-02-09 13:09:07 +01006461 if (trg->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006462 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006463 goto error;
6464 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006465 GETVAL(value, child, "value");
PavolVican9e81c6a2017-02-09 13:09:07 +01006466 if (lyp_check_identifier(value, LY_IDENT_PREFIX, trg, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006467 goto error;
6468 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006469 trg->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006470
Radek Krejci8d6b7422017-02-03 14:42:13 +01006471 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006472 goto error;
6473 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006474 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006475
6476 substmt_prev = "prefix";
Radek Krejcic071c542016-01-27 14:57:51 +01006477 } else if (submodule && !strcmp(child->name, "belongs-to")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006478 if (substmt_group > 0) {
6479 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6480 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6481 child->name, substmt_prev);
6482 goto error;
6483 }
6484
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006485 if (trg->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006486 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006487 goto error;
6488 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006489 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01006490 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006491 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006492 goto error;
6493 }
Radek Krejcif3886932015-06-04 17:36:06 +02006494
Radek Krejci8d6b7422017-02-03 14:42:13 +01006495 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_BELONGSTO, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006496 goto error;
6497 }
6498
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006499 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006500 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006501 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006502 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006503 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006504 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006505 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006506 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006507 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006508 goto error;
6509 }
6510 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006511 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006512 /* check here differs from a generic prefix check, since this prefix
6513 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02006514 */
Radek Krejci48464ed2016-03-17 15:44:09 +01006515 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006516 goto error;
6517 }
Radek Krejcic071c542016-01-27 14:57:51 +01006518 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02006519
Radek Krejci8d6b7422017-02-03 14:42:13 +01006520 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 +01006521 goto error;
6522 }
6523
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006524 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01006525 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02006526
Michal Vasko5de8a022017-02-08 10:57:26 +01006527 substmt_prev = "belongs-to";
6528
Radek Krejcieb00f512015-07-01 16:44:58 +02006529 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006530 } else if (!strcmp(child->name, "import")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006531 if (substmt_group > 1) {
6532 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6533 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6534 child->name, substmt_prev);
6535 goto error;
6536 }
6537 substmt_group = 1;
6538
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006539 c_imp++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006540
6541 substmt_prev = "import";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006542 } else if (!strcmp(child->name, "revision")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006543 if (substmt_group > 3) {
6544 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6545 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6546 child->name, substmt_prev);
6547 goto error;
6548 }
6549 substmt_group = 3;
6550
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006551 c_rev++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006552
PavolVican9e81c6a2017-02-09 13:09:07 +01006553 lyxml_unlink_elem(ctx, child, 2);
6554 lyxml_add_child(ctx, &revs, child);
6555
Michal Vasko5de8a022017-02-08 10:57:26 +01006556 substmt_prev = "revision";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006557 } else if (!strcmp(child->name, "typedef")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006558 substmt_group = 4;
6559
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006560 c_tpdf++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006561
6562 substmt_prev = "typedef";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006563 } else if (!strcmp(child->name, "identity")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006564 substmt_group = 4;
6565
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006566 c_ident++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006567
6568 substmt_prev = "identity";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006569 } else if (!strcmp(child->name, "include")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006570 if (substmt_group > 1) {
6571 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6572 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6573 child->name, substmt_prev);
6574 goto error;
6575 }
6576 substmt_group = 1;
6577
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006578 c_inc++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006579
6580 substmt_prev = "include";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006581 } else if (!strcmp(child->name, "augment")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006582 substmt_group = 4;
6583
Radek Krejcif5be10f2015-06-16 13:29:36 +02006584 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006585 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01006586 lyxml_unlink_elem(ctx, child, 2);
6587 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006588
Michal Vasko5de8a022017-02-08 10:57:26 +01006589 substmt_prev = "augment";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006590 } else if (!strcmp(child->name, "feature")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006591 substmt_group = 4;
6592
Radek Krejci3cf9e222015-06-18 11:37:50 +02006593 c_ftrs++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006594
Michal Vasko5de8a022017-02-08 10:57:26 +01006595 substmt_prev = "feature";
Michal Vasko5de8a022017-02-08 10:57:26 +01006596
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006597 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006598 } else if (!strcmp(child->name, "container") ||
6599 !strcmp(child->name, "leaf-list") ||
6600 !strcmp(child->name, "leaf") ||
6601 !strcmp(child->name, "list") ||
6602 !strcmp(child->name, "choice") ||
6603 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006604 !strcmp(child->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01006605 !strcmp(child->name, "anydata") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006606 !strcmp(child->name, "rpc") ||
6607 !strcmp(child->name, "notification")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006608 substmt_group = 4;
6609
Radek Krejcic071c542016-01-27 14:57:51 +01006610 lyxml_unlink_elem(ctx, child, 2);
6611 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006612
Michal Vasko5de8a022017-02-08 10:57:26 +01006613 substmt_prev = "data definition";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006614 } else if (!strcmp(child->name, "grouping")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006615 substmt_group = 4;
6616
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006617 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01006618 lyxml_unlink_elem(ctx, child, 2);
6619 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006620
Michal Vasko5de8a022017-02-08 10:57:26 +01006621 substmt_prev = "grouping";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006622 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006623 } else if (!strcmp(child->name, "description")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006624 if (substmt_group > 2) {
6625 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6626 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6627 child->name, substmt_prev);
6628 goto error;
6629 }
6630 substmt_group = 2;
6631
Radek Krejcic071c542016-01-27 14:57:51 +01006632 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006633 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006634 goto error;
6635 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006636 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006637 goto error;
6638 }
Radek Krejcic071c542016-01-27 14:57:51 +01006639 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006640 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006641 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006642 goto error;
6643 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006644
6645 substmt_prev = "description";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006646 } else if (!strcmp(child->name, "reference")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006647 if (substmt_group > 2) {
6648 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6649 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6650 child->name, substmt_prev);
6651 goto error;
6652 }
6653 substmt_group = 2;
6654
Radek Krejcic071c542016-01-27 14:57:51 +01006655 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006656 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006657 goto error;
6658 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006659 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006660 goto error;
6661 }
Radek Krejcic071c542016-01-27 14:57:51 +01006662 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006663 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006664 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006665 goto error;
6666 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006667
6668 substmt_prev = "reference";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006669 } else if (!strcmp(child->name, "organization")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006670 if (substmt_group > 2) {
6671 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6672 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6673 child->name, substmt_prev);
6674 goto error;
6675 }
6676 substmt_group = 2;
6677
Radek Krejcic071c542016-01-27 14:57:51 +01006678 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006679 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006680 goto error;
6681 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006682 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_ORGANIZATION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006683 goto error;
6684 }
Radek Krejcic071c542016-01-27 14:57:51 +01006685 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006686 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006687 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006688 goto error;
6689 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006690
6691 substmt_prev = "organization";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006692 } else if (!strcmp(child->name, "contact")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006693 if (substmt_group > 2) {
6694 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6695 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6696 child->name, substmt_prev);
6697 goto error;
6698 }
6699 substmt_group = 2;
6700
Radek Krejcic071c542016-01-27 14:57:51 +01006701 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006702 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006703 goto error;
6704 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006705 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_CONTACT, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006706 goto error;
6707 }
Radek Krejcic071c542016-01-27 14:57:51 +01006708 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006709 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006710 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006711 goto error;
6712 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006713
6714 substmt_prev = "contact";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006715 } else if (!strcmp(child->name, "yang-version")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006716 if (substmt_group > 0) {
6717 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6718 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6719 child->name, substmt_prev);
6720 goto error;
6721 }
6722
Radek Krejcic071c542016-01-27 14:57:51 +01006723 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006724 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006725 goto error;
6726 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006727 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02006728 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006729 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006730 goto error;
6731 }
Radek Krejcic071c542016-01-27 14:57:51 +01006732 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006733 if (!strcmp(value, "1")) {
6734 if (submodule) {
6735 if (module->version > 1) {
6736 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6737 goto error;
6738 }
6739 } else {
6740 module->version = 1;
6741 }
6742 } else {
6743 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006744 if (module->version < 2) {
Michal Vasko88de3e42016-06-29 11:05:32 +02006745 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6746 goto error;
6747 }
6748 } else {
6749 module->version = 2;
6750 }
6751 }
6752
Radek Krejci8d6b7422017-02-03 14:42:13 +01006753 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_VERSION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006754 goto error;
6755 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006756 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006757
Michal Vasko5de8a022017-02-08 10:57:26 +01006758 substmt_prev = "yang-version";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006759 } else if (!strcmp(child->name, "extension")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006760 substmt_group = 4;
6761
Radek Krejcia1a6b762016-11-14 09:53:38 +09006762 c_ext++;
Radek Krejci5166a892015-07-02 16:44:24 +02006763
Michal Vasko5de8a022017-02-08 10:57:26 +01006764 substmt_prev = "extension";
Radek Krejcia1a6b762016-11-14 09:53:38 +09006765 } else if (!strcmp(child->name, "deviation")) {
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006766 substmt_group = 4;
6767
Radek Krejcia1a6b762016-11-14 09:53:38 +09006768 c_dev++;
6769
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006770 substmt_prev = "deviation";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006771 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01006772 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006773 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006774 }
6775 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006776
Radek Krejcic071c542016-01-27 14:57:51 +01006777 /* check for mandatory statements */
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006778 if (submodule) {
6779 if (!submodule->prefix) {
6780 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
6781 goto error;
6782 }
6783 if (!version_flag) {
6784 /* check version compatibility with the main module */
6785 if (module->version > 1) {
6786 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6787 goto error;
6788 }
6789 }
6790 } else {
PavolVican9e81c6a2017-02-09 13:09:07 +01006791 if (!trg->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006792 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006793 goto error;
6794 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006795 if (!trg->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006796 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006797 goto error;
6798 }
6799 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02006800
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006801 /* allocate arrays for elements with cardinality of 0..n */
6802 if (c_imp) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006803 trg->imp = calloc(c_imp, sizeof *trg->imp);
Radek Krejcic071c542016-01-27 14:57:51 +01006804 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01006805 LOGMEM;
6806 goto error;
6807 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006808 }
6809 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006810 trg->rev = calloc(c_rev, sizeof *trg->rev);
6811 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01006812 LOGMEM;
6813 goto error;
6814 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006815 }
6816 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01006817 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
6818 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01006819 LOGMEM;
6820 goto error;
6821 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006822 }
6823 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01006824 trg->ident = calloc(c_ident, sizeof *trg->ident);
6825 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01006826 LOGMEM;
6827 goto error;
6828 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006829 }
6830 if (c_inc) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006831 trg->inc = calloc(c_inc, sizeof *trg->inc);
Radek Krejcic071c542016-01-27 14:57:51 +01006832 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01006833 LOGMEM;
6834 goto error;
6835 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006836 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006837 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01006838 trg->augment = calloc(c_aug, sizeof *trg->augment);
6839 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01006840 LOGMEM;
6841 goto error;
6842 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006843 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006844 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01006845 trg->features = calloc(c_ftrs, sizeof *trg->features);
6846 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01006847 LOGMEM;
6848 goto error;
6849 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006850 }
Radek Krejcieb00f512015-07-01 16:44:58 +02006851 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006852 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
6853 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01006854 LOGMEM;
6855 goto error;
6856 }
Radek Krejcieb00f512015-07-01 16:44:58 +02006857 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09006858 if (c_ext) {
6859 trg->extensions = calloc(c_ext, sizeof *trg->extensions);
6860 if (!trg->extensions) {
6861 LOGMEM;
6862 goto error;
6863 }
6864 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006865
PavolVican9e81c6a2017-02-09 13:09:07 +01006866 /* middle part 1 - process revision and then check whether this (sub)module was not already parsed, add it there */
6867 LY_TREE_FOR_SAFE(revs.child, next, child) {
Radek Krejci7417a082017-02-16 11:07:59 +01006868 r = fill_yin_revision(trg, child, &trg->rev[trg->rev_size], unres);
6869 trg->rev_size++;
6870 if (r) {
PavolVican9e81c6a2017-02-09 13:09:07 +01006871 goto error;
6872 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006873
Radek Krejci7417a082017-02-16 11:07:59 +01006874 /* check uniqueness of the revision date - not required by RFC */
6875 for (i = 0; i < (trg->rev_size - 1); i++) {
6876 if (!strcmp(trg->rev[i].date, trg->rev[trg->rev_size - 1].date)) {
6877 LOGWRN("Module's revisions are not unique (%s).", trg->rev[trg->rev_size - 1].date);
6878 break;
PavolVican9e81c6a2017-02-09 13:09:07 +01006879 }
6880 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006881
6882 lyxml_free(ctx, child);
6883 }
6884
6885 /* check the module with respect to the context now */
6886 if (!submodule) {
6887 switch (lyp_ctx_check_module(module)) {
6888 case -1:
6889 goto error;
6890 case 0:
6891 break;
6892 case 1:
6893 /* it's already there */
6894 ret = 1;
6895 goto error;
6896 }
6897 }
6898
6899 /* middle part 2 - process nodes with cardinality of 0..n except the data nodes and augments */
Michal Vasko2f7925f2015-10-21 15:06:56 +02006900 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02006901 if (!strcmp(child->name, "import")) {
Radek Krejcie534c132016-11-23 13:32:31 +01006902 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size], unres);
Radek Krejcic071c542016-01-27 14:57:51 +01006903 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006904 if (r) {
6905 goto error;
6906 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006907
Radek Krejci1d82ef62015-08-07 14:44:40 +02006908 } else if (!strcmp(child->name, "include")) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006909 r = fill_yin_include(module, submodule, child, &trg->inc[trg->inc_size], unres);
6910 trg->inc_size++;
6911 if (r) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006912 goto error;
6913 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006914
Radek Krejci1d82ef62015-08-07 14:44:40 +02006915 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006916 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
6917 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006918 if (r) {
6919 goto error;
6920 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006921
Radek Krejci1d82ef62015-08-07 14:44:40 +02006922 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006923 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
6924 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006925 if (r) {
6926 goto error;
6927 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006928
Radek Krejci1d82ef62015-08-07 14:44:40 +02006929 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006930 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
6931 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006932 if (r) {
6933 goto error;
6934 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006935
Radek Krejcia1a6b762016-11-14 09:53:38 +09006936 } else if (!strcmp(child->name, "extension")) {
Radek Krejcie534c132016-11-23 13:32:31 +01006937 r = fill_yin_extension(trg, child, &trg->extensions[trg->extensions_size], unres);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006938 trg->extensions_size++;
6939 if (r) {
6940 goto error;
6941 }
6942
Radek Krejci1d82ef62015-08-07 14:44:40 +02006943 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006944 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
6945 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02006946 if (r) {
6947 goto error;
6948 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006949 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006950 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006951
Radek Krejcie534c132016-11-23 13:32:31 +01006952 /* process extension instances */
Radek Krejci8ee94802017-02-10 12:38:40 +01006953 if (c_extinst) {
6954 /* some extensions may be already present from the substatements */
6955 reallocated = realloc(trg->ext, (c_extinst + trg->ext_size) * sizeof *trg->ext);
6956 if (!reallocated) {
6957 LOGMEM;
Radek Krejcie534c132016-11-23 13:32:31 +01006958 goto error;
6959 }
Radek Krejci8ee94802017-02-10 12:38:40 +01006960 trg->ext = reallocated;
6961
6962 /* init memory */
6963 memset(&trg->ext[trg->ext_size], 0, c_extinst * sizeof *trg->ext);
6964
6965 LY_TREE_FOR_SAFE(exts.child, next, child) {
6966 r = lyp_yin_fill_ext(trg, LYEXT_PAR_MODULE, 0, 0, trg, child, &trg->ext, trg->ext_size, unres);
6967 trg->ext_size++;
6968 if (r) {
6969 goto error;
6970 }
6971 }
Radek Krejcie534c132016-11-23 13:32:31 +01006972 }
6973
Radek Krejcif5be10f2015-06-16 13:29:36 +02006974 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01006975 * refer to them. Submodule's data nodes are stored in the
6976 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006977 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006978 LY_TREE_FOR_SAFE(grps.child, next, child) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006979 node = read_yin_grouping(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006980 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006981 goto error;
6982 }
Radek Krejci74705112015-06-05 10:25:44 +02006983
Michal Vasko345da0a2015-12-02 10:35:55 +01006984 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006985 }
Radek Krejci74705112015-06-05 10:25:44 +02006986
Radek Krejcif5be10f2015-06-16 13:29:36 +02006987 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006988 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02006989
Radek Krejci1d82ef62015-08-07 14:44:40 +02006990 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006991 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006992 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006993 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006994 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006995 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006996 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006997 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006998 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006999 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007000 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02007001 node = read_yin_uses(trg, NULL, child, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02007002 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02007003 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 1, unres);
7004 } else if (!strcmp(child->name, "anydata")) {
7005 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007006 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02007007 node = read_yin_rpc_action(trg, NULL, child, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02007008 } else if (!strcmp(child->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02007009 node = read_yin_notif(trg, NULL, child, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007010 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02007011 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007012 goto error;
7013 }
Radek Krejci25d782a2015-05-22 15:03:23 +02007014
Michal Vasko345da0a2015-12-02 10:35:55 +01007015 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007016 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02007017
Michal Vasko2f7925f2015-10-21 15:06:56 +02007018 /* ... and finally augments (last, so we can augment our data, for instance) */
7019 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01007020 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
7021 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02007022
Michal Vasko2f7925f2015-10-21 15:06:56 +02007023 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02007024 goto error;
7025 }
Michal Vasko345da0a2015-12-02 10:35:55 +01007026 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02007027 }
7028
PavolVican9e81c6a2017-02-09 13:09:07 +01007029 return 0;
Radek Krejciefaeba32015-05-27 14:30:57 +02007030
7031error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007032 while (root.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007033 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007034 }
7035 while (grps.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007036 lyxml_free(ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007037 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007038 while (augs.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007039 lyxml_free(ctx, augs.child);
7040 }
7041 while (revs.child) {
7042 lyxml_free(ctx, revs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02007043 }
Radek Krejcie534c132016-11-23 13:32:31 +01007044 while (exts.child) {
7045 lyxml_free(module->ctx, exts.child);
7046 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007047
PavolVican9e81c6a2017-02-09 13:09:07 +01007048 return ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007049}
7050
Michal Vasko0d343d12015-08-24 14:57:36 +02007051/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007052struct lys_submodule *
7053yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02007054{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007055 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01007056 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007057 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02007058
Michal Vasko5a721fd2016-02-16 12:16:48 +01007059 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02007060
Radek Krejci722b0072016-02-01 17:09:45 +01007061 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007062 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01007063 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007064 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007065
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007066 /* check root element */
7067 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01007068 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007069 goto error;
7070 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007071
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007072 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01007073 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007074 goto error;
7075 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007076
Michal Vasko5a721fd2016-02-16 12:16:48 +01007077 submodule = calloc(1, sizeof *submodule);
7078 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007079 LOGMEM;
7080 goto error;
7081 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007082
Michal Vasko5a721fd2016-02-16 12:16:48 +01007083 submodule->ctx = module->ctx;
7084 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
7085 submodule->type = 1;
7086 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02007087
Michal Vasko5a721fd2016-02-16 12:16:48 +01007088 LOGVRB("Reading submodule \"%s\".", submodule->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007089 /* module cannot be changed in this case and 1 cannot be returned */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007090 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007091 goto error;
7092 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007093
Radek Krejci33fc4772017-01-26 16:00:35 +01007094 lyp_sort_revisions((struct lys_module *)submodule);
7095
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007096 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01007097 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02007098
Michal Vasko5a721fd2016-02-16 12:16:48 +01007099 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007100 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02007101
7102error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007103 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007104 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01007105 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01007106
Michal Vasko5a721fd2016-02-16 12:16:48 +01007107 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01007108 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01007109 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01007110 }
7111
Michal Vasko5a721fd2016-02-16 12:16:48 +01007112 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01007113
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007114 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
7115 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007116 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007117 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02007118}
7119
Michal Vasko0d343d12015-08-24 14:57:36 +02007120/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02007121struct lys_module *
Radek Krejci37f9ba32017-02-10 16:50:35 +01007122yin_read_module_(struct ly_ctx *ctx, struct lyxml_elem *yin, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02007123{
Pavol Vicanc99b59e2016-03-22 15:46:39 +01007124 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01007125 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007126 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01007127 int ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007128
Radek Krejcic071c542016-01-27 14:57:51 +01007129 unres = calloc(1, sizeof *unres);
7130 if (!unres) {
7131 LOGMEM;
7132 return NULL;
7133 }
7134
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007135 /* check root element */
7136 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci9a909bd2016-10-24 15:45:51 +02007137 if (ly_strequal("submodule", yin->name, 0)) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007138 LOGVAL(LYE_SUBMODULE, LY_VLOG_NONE, NULL);
7139 } else {
7140 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci9a909bd2016-10-24 15:45:51 +02007141 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007142 goto error;
7143 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007145 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01007146 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007147 goto error;
7148 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007150 module = calloc(1, sizeof *module);
7151 if (!module) {
7152 LOGMEM;
7153 goto error;
7154 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007155
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007156 module->ctx = ctx;
7157 module->name = lydict_insert(ctx, value, strlen(value));
7158 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02007159 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02007160
Michal Vasko9f258e42016-02-11 11:36:27 +01007161 LOGVRB("Reading module \"%s\".", module->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007162 ret = read_sub_module(module, NULL, yin, unres);
7163 if (ret == -1) {
Radek Krejcic071c542016-01-27 14:57:51 +01007164 goto error;
7165 }
7166
PavolVican9e81c6a2017-02-09 13:09:07 +01007167 if (ret == 1) {
7168 assert(!unres->count);
7169 } else {
7170 /* resolve rest of unres items */
7171 if (unres->count && resolve_unres_schema(module, unres)) {
7172 goto error;
7173 }
7174
7175 /* check correctness of includes */
7176 if (lyp_check_include_missing(module)) {
7177 goto error;
7178 }
Michal Vasko7b460e52017-02-10 14:50:26 +01007179
7180 /* remove our submodules from the parsed submodules list */
7181 lyp_del_includedup(module);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007182 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007183
Radek Krejci95f22ae2017-01-20 14:25:53 +01007184 lyp_sort_revisions(module);
Radek Krejci6bd2c022017-02-01 15:04:49 +01007185
7186 if (lyp_rfn_apply_ext(module) || lyp_deviation_apply_ext(module)) {
7187 goto error;
7188 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01007189
Radek Krejciff4874d2016-03-07 12:30:50 +01007190 if (revision) {
7191 /* check revision of the parsed model */
7192 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01007193 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
7194 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01007195 goto error;
7196 }
7197 }
7198
PavolVican9e81c6a2017-02-09 13:09:07 +01007199 /* add into context if not already there */
7200 if (!ret) {
7201 if (module->deviation_size && !module->implemented) {
7202 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
7203 /* deviations always causes target to be made implemented,
7204 * but augents and leafrefs not, so we have to apply them now */
7205 if (lys_set_implemented(module)) {
7206 goto error;
7207 }
7208 }
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007209
PavolVican9e81c6a2017-02-09 13:09:07 +01007210 if (lyp_ctx_add_module(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02007211 goto error;
7212 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007213 } else {
7214 /* free what was parsed */
7215 lys_free(module, NULL, 0);
7216
7217 /* get the model from the context */
7218 module = (struct lys_module *)ly_ctx_get_module(ctx, value, revision);
7219 assert(module);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007220 }
7221
Radek Krejcic071c542016-01-27 14:57:51 +01007222 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01007223 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007224 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007225
7226error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007227 /* cleanup */
Radek Krejcib8c07b82016-02-12 11:11:55 +01007228 unres_schema_free(module, &unres);
7229
7230 if (!module) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007231 if (ly_vecode != LYVE_SUBMODULE) {
7232 LOGERR(ly_errno, "Module parsing failed.");
7233 }
Radek Krejcib8c07b82016-02-12 11:11:55 +01007234 return NULL;
7235 }
7236
7237 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02007238
Michal Vaskocf0489e2017-02-13 11:57:45 +01007239 lyp_del_includedup(module);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007240 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01007241 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007242 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007243}
Radek Krejci8d6b7422017-02-03 14:42:13 +01007244
Radek Krejci37f9ba32017-02-10 16:50:35 +01007245/* logs directly */
7246struct lys_module *
7247yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
7248{
7249 struct lyxml_elem *yin;
7250 struct lys_module *result;
7251
7252 yin = lyxml_parse_mem(ctx, data, 0);
7253 if (!yin) {
7254 LOGERR(ly_errno, "Module parsing failed.");
7255 return NULL;
7256 }
7257
7258 result = yin_read_module_(ctx, yin, revision, implement);
7259
7260 lyxml_free(ctx, yin);
7261
7262 return result;
7263}
7264
Radek Krejcic1885952017-02-07 09:37:51 +01007265static int
7266yin_parse_extcomplex_bool(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007267 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007268 const char *true_val, const char *false_val, struct unres_schema *unres)
7269{
7270 uint8_t *val;
7271 const char *str;
7272 struct lyext_substmt *info;
7273
7274 val = lys_ext_complex_get_substmt(stmt, ext, &info);
7275 if (!val) {
7276 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7277 return EXIT_FAILURE;
7278 }
7279 if (*val) {
7280 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7281 return EXIT_FAILURE;
7282 }
7283
Radek Krejcibe336392017-02-07 10:54:24 +01007284 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007285 return EXIT_FAILURE;
7286 }
7287
7288 str = lyxml_get_attr(node, "value", NULL);
7289 if (!str) {
7290 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
7291 } else if (true_val && !strcmp(true_val, str)) {
7292 /* true value */
7293 *val = 1;
7294 } else if (false_val && !strcmp(false_val, str)) {
7295 /* false value */
7296 *val = 2;
7297 } else {
7298 /* unknown value */
7299 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
7300 return EXIT_FAILURE;
7301 }
7302
7303 return EXIT_SUCCESS;
7304}
7305
Radek Krejci8d6b7422017-02-03 14:42:13 +01007306/*
7307 * argelem - 1 if the value is stored in a standalone YIN element, 0 if stored as attribute
7308 * argname - name of the element/attribute where the value is stored
7309 */
7310static int
7311yin_parse_extcomplex_str(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007312 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejci8d6b7422017-02-03 14:42:13 +01007313 int argelem, const char *argname, struct unres_schema *unres)
7314{
7315 int c;
PavolVican99c70722017-02-18 17:25:52 +01007316 const char **str, ***p = NULL, *value;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007317 void *reallocated;
7318 struct lyext_substmt *info;
7319
7320 str = lys_ext_complex_get_substmt(stmt, ext, &info);
7321 if (!str) {
7322 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7323 return EXIT_FAILURE;
7324 }
7325 if (info->cardinality < LY_STMT_CARD_SOME && *str) {
7326 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7327 return EXIT_FAILURE;
7328 }
7329
7330 c = 0;
7331 if (info->cardinality >= LY_STMT_CARD_SOME) {
7332 /* there can be multiple instances, str is actually const char *** */
7333 p = (const char ***)str;
Radek Krejci56c80412017-02-09 10:44:16 +01007334 if (!p[0]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007335 /* allocate initial array */
Radek Krejci56c80412017-02-09 10:44:16 +01007336 p[0] = malloc(2 * sizeof(const char *));
7337 if (stmt == LY_STMT_BELONGSTO) {
7338 /* allocate another array for the belongs-to's prefixes */
7339 p[1] = malloc(2 * sizeof(const char *));
PavolVican99c70722017-02-18 17:25:52 +01007340 } else if (stmt == LY_STMT_ARGUMENT) {
7341 /* allocate another array for the yin element */
7342 p[1] = malloc(2 * sizeof(uint8_t));
Radek Krejci56c80412017-02-09 10:44:16 +01007343 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007344 } else {
Radek Krejci56c80412017-02-09 10:44:16 +01007345 /* get the index in the array to add new item */
7346 for (c = 0; p[0][c]; c++);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007347 }
Radek Krejci56c80412017-02-09 10:44:16 +01007348 str = p[0];
Radek Krejci8d6b7422017-02-03 14:42:13 +01007349 }
Radek Krejcibe336392017-02-07 10:54:24 +01007350 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, stmt, c, unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007351 return EXIT_FAILURE;
7352 }
7353
7354 if (argelem) {
Radek Krejci56c80412017-02-09 10:44:16 +01007355 str[c] = read_yin_subnode(mod->ctx, node, argname);
7356 if (!str[c]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007357 return EXIT_FAILURE;
7358 }
Radek Krejci56c80412017-02-09 10:44:16 +01007359 } else {
7360 str[c] = lyxml_get_attr(node, argname, NULL);
7361 if (!str[c]) {
7362 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, argname, node->name);
7363 return EXIT_FAILURE;
7364 } else {
7365 str[c] = lydict_insert(mod->ctx, str[c], 0);
7366 }
7367
7368 if (stmt == LY_STMT_BELONGSTO) {
7369 /* get the belongs-to's mandatory prefix substatement */
7370 if (!node->child) {
7371 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", node->name);
7372 return EXIT_FAILURE;
7373 } else if (strcmp(node->child->name, "prefix")) {
7374 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
7375 return EXIT_FAILURE;
7376 } else if (node->child->next) {
7377 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
7378 return EXIT_FAILURE;
7379 }
7380 /* and now finally get the value */
7381 if (p) {
7382 str = p[1];
7383 } else {
7384 str++;
7385 }
7386 str[c] = lyxml_get_attr(node->child, "value", ((void *)0));
7387 if (!str[c]) {
7388 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
7389 return EXIT_FAILURE;
7390 }
7391 str[c] = lydict_insert(mod->ctx, str[c], 0);
7392
7393 if (!str[c] || lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node->child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
7394 return EXIT_FAILURE;
7395 }
PavolVican99c70722017-02-18 17:25:52 +01007396 } else if (stmt == LY_STMT_ARGUMENT) {
7397 str = (p) ? p[1] : str + 1;
7398 if (!node->child) {
7399 /* default value of yin element */
7400 ((uint8_t *)str)[c] = 2;
7401 } else {
7402 /* get optional yin-element substatement */
7403 if (strcmp(node->child->name, "yin-element")) {
7404 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
7405 return EXIT_FAILURE;
7406 } else if (node->child->next) {
7407 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
7408 return EXIT_FAILURE;
7409 } else {
7410 /* and now finally get the value */
7411 value = lyxml_get_attr(node->child, "value", NULL);
7412 if (!value) {
7413 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
7414 return EXIT_FAILURE;
7415 }
7416 if (ly_strequal(value, "true", 0)) {
7417 ((uint8_t *)str)[c] = 1;
7418 } else if (ly_strequal(value, "false", 0)) {
7419 ((uint8_t *)str)[c] = 2;
7420 } else {
7421 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
7422 return EXIT_FAILURE;
7423 }
7424
7425 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node->child, LYEXT_SUBSTMT_YINELEM, c, unres)) {
7426 return EXIT_FAILURE;
7427 }
7428 }
7429 }
Radek Krejci56c80412017-02-09 10:44:16 +01007430 }
7431 }
7432 if (p) {
7433 /* enlarge the array(s) */
7434 reallocated = realloc(p[0], (c + 2) * sizeof(const char *));
7435 if (!reallocated) {
7436 LOGMEM;
7437 lydict_remove(mod->ctx, p[0][c]);
7438 p[0][c] = NULL;
7439 return EXIT_FAILURE;
7440 }
7441 p[0] = reallocated;
7442 p[0][c + 1] = NULL;
7443
7444 if (stmt == LY_STMT_BELONGSTO) {
7445 /* enlarge the second belongs-to's array with prefixes */
7446 reallocated = realloc(p[1], (c + 2) * sizeof(const char *));
7447 if (!reallocated) {
7448 LOGMEM;
7449 lydict_remove(mod->ctx, p[1][c]);
7450 p[1][c] = NULL;
7451 return EXIT_FAILURE;
7452 }
7453 p[1] = reallocated;
7454 p[1][c + 1] = NULL;
PavolVican99c70722017-02-18 17:25:52 +01007455 } else if (stmt == LY_STMT_ARGUMENT){
7456 /* enlarge the second argument's array with yin element */
7457 reallocated = realloc(p[1], (c + 2) * sizeof(uint8_t));
7458 if (!reallocated) {
7459 LOGMEM;
7460 ((uint8_t *)p[1])[c] = 0;
7461 return EXIT_FAILURE;
7462 }
7463 p[1] = reallocated;
7464 ((uint8_t *)p[1])[c + 1] = 0;
Radek Krejci56c80412017-02-09 10:44:16 +01007465 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007466 }
7467
7468 return EXIT_SUCCESS;
7469}
7470
7471static void *
7472yin_getplace_for_extcomplex_flags(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt,
7473 uint16_t mask)
7474{
7475 void *data;
7476 struct lyext_substmt *info;
7477
7478 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7479 if (!data) {
7480 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7481 return NULL;
7482 }
7483 if (info->cardinality < LY_STMT_CARD_SOME && ((*(uint16_t *)data) & mask)) {
7484 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7485 return NULL;
7486 }
7487
7488 return data;
7489}
7490
Radek Krejcic1885952017-02-07 09:37:51 +01007491static int
7492yin_parse_extcomplex_flag(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007493 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007494 const char *val1_str, const char *val2_str, uint16_t mask,
7495 uint16_t val1, uint16_t val2, struct unres_schema *unres)
7496{
7497 uint16_t *val;
7498 const char *str;
7499
7500 val = yin_getplace_for_extcomplex_flags(node, ext, stmt, mask);
7501 if (!val) {
7502 return EXIT_FAILURE;
7503 }
7504
7505 str = lyxml_get_attr(node, "value", NULL);
7506 if (!str) {
7507 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
7508 } else if (!strcmp(val1_str, str)) {
7509 *val = *val | val1;
7510 } else if (!strcmp(val2_str, str)) {
7511 *val = *val | val2;
7512 } else {
7513 /* unknown value */
7514 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
7515 return EXIT_FAILURE;
7516 }
Radek Krejcibe336392017-02-07 10:54:24 +01007517 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007518 return EXIT_FAILURE;
7519 }
7520 return EXIT_SUCCESS;
7521}
7522
Radek Krejcif95b6292017-02-13 15:57:37 +01007523static struct lys_node **
7524yin_getplace_for_extcomplex_node(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7525{
7526 struct lyext_substmt *info;
7527 struct lys_node **snode, *siter;
7528
7529 snode = lys_ext_complex_get_substmt(stmt, ext, &info);
7530 if (!snode) {
7531 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7532 return NULL;
7533 }
7534 if (info->cardinality < LY_STMT_CARD_SOME) {
7535 LY_TREE_FOR(*snode, siter) {
7536 if (stmt == lys_snode2stmt(siter->nodetype)) {
7537 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7538 return NULL;
7539 }
7540 }
7541 }
7542
7543 return snode;
7544}
7545
Radek Krejci8d6b7422017-02-03 14:42:13 +01007546static void **
7547yin_getplace_for_extcomplex_struct(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7548{
7549 int c;
7550 void **data, ***p = NULL;
7551 void *reallocated;
7552 struct lyext_substmt *info;
7553
7554 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7555 if (!data) {
7556 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7557 return NULL;
7558 }
7559 if (info->cardinality < LY_STMT_CARD_SOME && *data) {
7560 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7561 return NULL;
7562 }
7563
7564 c = 0;
7565 if (info->cardinality >= LY_STMT_CARD_SOME) {
7566 /* there can be multiple instances, so instead of pointer to array,
7567 * we have in data pointer to pointer to array */
7568 p = (void ***)data;
7569 data = *p;
7570 if (!data) {
7571 /* allocate initial array */
7572 *p = data = malloc(2 * sizeof(void *));
7573 } else {
7574 for (c = 0; *data; data++, c++);
7575 }
7576 }
7577
7578 if (p) {
7579 /* enlarge the array */
7580 reallocated = realloc(*p, (c + 2) * sizeof(void *));
7581 if (!reallocated) {
7582 LOGMEM;
7583 return NULL;
7584 }
7585 *p = reallocated;
7586 data = *p;
7587 data[c + 1] = NULL;
7588 }
7589
7590 return &data[c];
7591}
7592
7593int
7594lyp_yin_parse_complex_ext(struct lys_module *mod, struct lys_ext_instance_complex *ext, struct lyxml_elem *yin,
7595 struct unres_schema *unres)
7596{
Radek Krejciaa9c5202017-02-15 16:10:14 +01007597 struct lyxml_elem *next, *node, *child;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007598 struct lys_type **type;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007599 void **pp, *p, *reallocated;
Radek Krejciaa9c5202017-02-15 16:10:14 +01007600 const char *value, *name;
7601 char *endptr, modifier;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007602 struct lyext_substmt *info;
7603 long int v;
Radek Krejci5496fae2017-02-10 13:26:48 +01007604 long long int ll;
7605 unsigned long u;
Radek Krejci7417a082017-02-16 11:07:59 +01007606 int i, j;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007607
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007608#define YIN_EXTCOMPLEX_GETPLACE(STMT, TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007609 p = lys_ext_complex_get_substmt(STMT, ext, &info); \
7610 if (!p) { \
7611 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
7612 goto error; \
7613 } \
7614 if (info->cardinality < LY_STMT_CARD_SOME && (*(TYPE*)p)) { \
7615 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
7616 goto error; \
7617 } \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007618 pp = NULL; i = 0; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007619 if (info->cardinality >= LY_STMT_CARD_SOME) { \
7620 /* there can be multiple instances */ \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007621 pp = p; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007622 if (!(*pp)) { \
7623 *pp = malloc(2 * sizeof(TYPE)); /* allocate initial array */ \
7624 } else { \
7625 for (i = 0; (*(TYPE**)pp)[i]; i++); \
7626 } \
7627 p = &(*(TYPE**)pp)[i]; \
7628 }
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007629#define YIN_EXTCOMPLEX_ENLARGE(TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007630 if (pp) { \
7631 /* enlarge the array */ \
7632 reallocated = realloc(*pp, (i + 2) * sizeof(TYPE*)); \
7633 if (!reallocated) { \
7634 LOGMEM; \
7635 goto error; \
7636 } \
7637 *pp = reallocated; \
7638 (*(TYPE**)pp)[i + 1] = 0; \
7639 }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007640#define YIN_EXTCOMPLEX_PARSE_SNODE(STMT, FUNC, ARGS...) \
7641 pp = (void**)yin_getplace_for_extcomplex_node(node, ext, STMT); \
7642 if (!pp) { goto error; } \
7643 if (!FUNC(mod, (struct lys_node*)ext, node, ##ARGS, unres)) { goto error; }
7644#define YIN_EXTCOMPLEX_PARSE_RESTR(STMT) \
7645 YIN_EXTCOMPLEX_GETPLACE(STMT, struct lys_restr*); \
7646 GETVAL(value, node, "value"); \
7647 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr)); \
7648 (*(struct lys_restr **)p)->expr = lydict_insert(mod->ctx, value, 0); \
7649 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) { \
7650 goto error; \
7651 } \
7652 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007653
Radek Krejci8d6b7422017-02-03 14:42:13 +01007654 LY_TREE_FOR_SAFE(yin->child, next, node) {
7655 if (!node->ns) {
7656 /* garbage */
7657 } else if (node->ns == yin->ns && (ext->flags & LYS_YINELEM) && ly_strequal(node->name, ext->def->argument, 1)) {
7658 /* we have the extension's argument */
7659 if (ext->arg_value) {
7660 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
7661 goto error;
7662 }
7663 ext->arg_value = node->content;
7664 node->content = NULL;
7665 } else if (strcmp(node->ns->value, LY_NSYIN)) {
7666 /* extension */
7667 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_SELF, 0, unres)) {
7668 goto error;
7669 }
7670 } else if (!strcmp(node->name, "description")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007671 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DESCRIPTION, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007672 goto error;
7673 }
7674 } else if (!strcmp(node->name, "reference")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007675 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REFERENCE, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007676 goto error;
7677 }
7678 } else if (!strcmp(node->name, "units")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007679 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_UNITS, 0, "name", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007680 goto error;
7681 }
7682 } else if (!strcmp(node->name, "type")) {
7683 type = (struct lys_type **)yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPE);
7684 if (!type) {
7685 goto error;
7686 }
7687 /* allocate type structure */
7688 (*type) = calloc(1, sizeof **type);
7689
7690 /* HACK for unres */
Radek Krejci63fc0962017-02-15 13:20:18 +01007691 lyxml_unlink(mod->ctx, node);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007692 (*type)->der = (struct lys_tpdf *)node;
7693 (*type)->parent = (struct lys_tpdf *)ext;
7694
7695 if (unres_schema_add_node(mod, unres, *type, UNRES_TYPE_DER_EXT, NULL) == -1) {
7696 (*type)->der = NULL;
7697 goto error;
7698 }
7699 continue; /* skip lyxml_free() */
Radek Krejci63fc0962017-02-15 13:20:18 +01007700 } else if (!strcmp(node->name, "typedef")) {
7701 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPEDEF);
7702 if (!pp) {
7703 goto error;
7704 }
7705 /* allocate typedef structure */
7706 (*pp) = calloc(1, sizeof(struct lys_tpdf));
7707
7708 if (fill_yin_typedef(mod, (struct lys_node *)ext, node, *((struct lys_tpdf **)pp), unres)) {
7709 goto error;
7710 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007711 } else if (!strcmp(node->name, "if-feature")) {
7712 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_IFFEATURE);
7713 if (!pp) {
7714 goto error;
7715 }
7716 /* allocate iffeature structure */
7717 (*pp) = calloc(1, sizeof(struct lys_iffeature));
7718
7719 if (fill_yin_iffeature((struct lys_node *)ext, 0, node, *((struct lys_iffeature **)pp), unres)) {
7720 goto error;
7721 }
7722 } else if (!strcmp(node->name, "status")) {
7723 p = yin_getplace_for_extcomplex_flags(node, ext, LY_STMT_STATUS, LYS_STATUS_MASK);
7724 if (!p) {
7725 goto error;
7726 }
7727
7728 GETVAL(value, node, "value");
7729 if (!strcmp(value, "current")) {
7730 *(uint16_t*)p |= LYS_STATUS_CURR;
7731 } else if (!strcmp(value, "deprecated")) {
7732 *(uint16_t*)p |= LYS_STATUS_DEPRC;
7733 } else if (!strcmp(value, "obsolete")) {
7734 *(uint16_t*)p |= LYS_STATUS_OBSLT;
7735 } else {
7736 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
7737 goto error;
7738 }
7739
7740 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, 0, unres)) {
7741 goto error;
7742 }
Radek Krejcic1885952017-02-07 09:37:51 +01007743 } else if (!strcmp(node->name, "config")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007744 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY, "true", "false", LYS_CONFIG_MASK,
Radek Krejcic1885952017-02-07 09:37:51 +01007745 LYS_CONFIG_W | LYS_CONFIG_SET, LYS_CONFIG_R | LYS_CONFIG_SET, unres)) {
7746 goto error;
7747 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007748 } else if (!strcmp(node->name, "argument")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007749 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ARGUMENT, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007750 goto error;
7751 }
7752 } else if (!strcmp(node->name, "default")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007753 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DEFAULT, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007754 goto error;
7755 }
Radek Krejcic1885952017-02-07 09:37:51 +01007756 } else if (!strcmp(node->name, "mandatory")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007757 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY,
Radek Krejcic1885952017-02-07 09:37:51 +01007758 "true", "false", LYS_MAND_MASK, LYS_MAND_TRUE, LYS_MAND_FALSE, unres)) {
7759 goto error;
7760 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007761 } else if (!strcmp(node->name, "error-app-tag")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007762 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRTAG, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007763 goto error;
7764 }
7765 } else if (!strcmp(node->name, "error-message")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007766 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRMSG, 1, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007767 goto error;
7768 }
7769 } else if (!strcmp(node->name, "prefix")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007770 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PREFIX, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007771 goto error;
7772 }
7773 } else if (!strcmp(node->name, "namespace")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007774 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_NAMESPACE, 0, "uri", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007775 goto error;
7776 }
7777 } else if (!strcmp(node->name, "presence")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007778 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PRESENCE, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007779 goto error;
7780 }
7781 } else if (!strcmp(node->name, "revision-date")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007782 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REVISIONDATE, 0, "date", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007783 goto error;
7784 }
7785 } else if (!strcmp(node->name, "key")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007786 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_KEY, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007787 goto error;
7788 }
7789 } else if (!strcmp(node->name, "base")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007790 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BASE, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007791 goto error;
7792 }
Radek Krejcic1885952017-02-07 09:37:51 +01007793 } else if (!strcmp(node->name, "ordered-by")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007794 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_ORDEREDBY,
7795 "user", "system", LYS_USERORDERED, LYS_USERORDERED, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007796 goto error;
7797 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007798 } else if (!strcmp(node->name, "belongs-to")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007799 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BELONGSTO, 0, "module", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007800 goto error;
7801 }
7802 } else if (!strcmp(node->name, "contact")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007803 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_CONTACT, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007804 goto error;
7805 }
7806 } else if (!strcmp(node->name, "organization")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007807 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ORGANIZATION, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007808 goto error;
7809 }
7810 } else if (!strcmp(node->name, "path")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007811 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PATH, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007812 goto error;
7813 }
Radek Krejcic1885952017-02-07 09:37:51 +01007814 } else if (!strcmp(node->name, "require-instance")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007815 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_REQINSTANCE, "true", "false", unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007816 goto error;
7817 }
7818 } else if (!strcmp(node->name, "modifier")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007819 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_MODIFIER, "invert-match", NULL, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007820 goto error;
7821 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007822 } else if (!strcmp(node->name, "fraction-digits")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007823 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_DIGITS, uint8_t);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007824
7825 GETVAL(value, node, "value");
7826 v = strtol(value, NULL, 10);
7827
7828 /* range check */
7829 if (v < 1 || v > 18) {
7830 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
7831 goto error;
7832 }
7833
7834 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, i, unres)) {
7835 goto error;
7836 }
7837
7838 /* store the value */
7839 (*(uint8_t *)p) = (uint8_t)v;
7840
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007841 YIN_EXTCOMPLEX_ENLARGE(uint8_t);
Radek Krejci5496fae2017-02-10 13:26:48 +01007842 } else if (!strcmp(node->name, "max-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007843 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MAX, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007844
7845 GETVAL(value, node, "value");
7846 while (isspace(value[0])) {
7847 value++;
7848 }
7849
7850 if (!strcmp(value, "unbounded")) {
7851 u = 0;
7852 } else {
7853 /* convert it to uint32_t */
7854 errno = 0; endptr = NULL;
7855 u = strtoul(value, &endptr, 10);
7856 if (*endptr || value[0] == '-' || errno || u == 0 || u > UINT32_MAX) {
7857 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007858 goto error;
7859 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007860 }
Radek Krejci5496fae2017-02-10 13:26:48 +01007861
7862 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
7863 goto error;
7864 }
7865
7866 /* store the value */
Radek Krejcif8d05c22017-02-10 15:33:35 +01007867 *(uint32_t **)p = malloc(sizeof(uint32_t));
7868 (**(uint32_t **)p) = (uint32_t)u;
Radek Krejci5496fae2017-02-10 13:26:48 +01007869
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007870 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007871 } else if (!strcmp(node->name, "min-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007872 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MIN, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007873
7874 GETVAL(value, node, "value");
7875 while (isspace(value[0])) {
7876 value++;
7877 }
7878
7879 /* convert it to uint32_t */
7880 errno = 0;
7881 endptr = NULL;
7882 u = strtoul(value, &endptr, 10);
7883 if (*endptr || value[0] == '-' || errno || u > UINT32_MAX) {
7884 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
7885 goto error;
7886 }
7887
7888 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
7889 goto error;
7890 }
7891
7892 /* store the value */
Radek Krejcif8d05c22017-02-10 15:33:35 +01007893 *(uint32_t **)p = malloc(sizeof(uint32_t));
7894 (**(uint32_t **)p) = (uint32_t)u;
Radek Krejci5496fae2017-02-10 13:26:48 +01007895
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007896 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci06a9aa02017-02-17 10:50:24 +01007897 } else if (!strcmp(node->name, "value")) {
PavolVican2ed9f4e2017-02-16 00:08:45 +01007898 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_VALUE, int32_t*);
7899
7900 GETVAL(value, node, "value");
7901 while (isspace(value[0])) {
7902 value++;
7903 }
7904
7905 /* convert it to int32_t */
Radek Krejci9326fc02017-02-16 09:57:40 +01007906 ll = strtoll(value, NULL, 10);
PavolVican2ed9f4e2017-02-16 00:08:45 +01007907
7908 /* range check */
Radek Krejci9326fc02017-02-16 09:57:40 +01007909 if (ll < INT32_MIN || ll > INT32_MAX) {
PavolVican2ed9f4e2017-02-16 00:08:45 +01007910 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
7911 goto error;
7912 }
7913
7914 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_VALUE, i, unres)) {
7915 goto error;
7916 }
7917
7918 /* store the value */
7919 *(int32_t **)p = malloc(sizeof(int32_t));
Radek Krejci9326fc02017-02-16 09:57:40 +01007920 (**(int32_t **)p) = (int32_t)ll;
PavolVican2ed9f4e2017-02-16 00:08:45 +01007921
7922 YIN_EXTCOMPLEX_ENLARGE(int32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007923 } else if (!strcmp(node->name, "position")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007924 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_POSITION, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007925
7926 GETVAL(value, node, "value");
7927 ll = strtoll(value, NULL, 10);
7928
7929 /* range check */
7930 if (ll < 0 || ll > 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_POSITION, 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)ll;
Radek Krejci5496fae2017-02-10 13:26:48 +01007942
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007943 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci37f9ba32017-02-10 16:50:35 +01007944 } else if (!strcmp(node->name, "module")) {
7945 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MODULE);
7946 if (!pp) {
7947 goto error;
7948 }
7949
7950 *(struct lys_module **)pp = yin_read_module_(mod->ctx, node, NULL, mod->implemented);
7951 if (!(*pp)) {
7952 goto error;
7953 }
Radek Krejcic5cc5302017-02-16 10:07:46 +01007954 } else if (!strcmp(node->name, "when")) {
7955 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_WHEN, struct lys_when*);
7956
7957 *(struct lys_when**)p = read_yin_when(mod, node, unres);
7958 if (!*(struct lys_when**)p) {
7959 goto error;
7960 }
7961
7962 YIN_EXTCOMPLEX_ENLARGE(struct lys_when*);
Radek Krejci7417a082017-02-16 11:07:59 +01007963 } else if (!strcmp(node->name, "revision")) {
7964 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_REVISION, struct lys_revision*);
7965
7966 *(struct lys_revision**)p = calloc(1, sizeof(struct lys_revision));
7967 if (fill_yin_revision(mod, node, *(struct lys_revision**)p, unres)) {
7968 goto error;
7969 }
7970
7971 /* check uniqueness of the revision dates - not required by RFC */
7972 if (pp) {
7973 for (j = 0; j < i; j++) {
7974 if (!strcmp((*(struct lys_revision***)pp)[j]->date, (*(struct lys_revision**)p)->date)) {
7975 LOGWRN("Module's revisions are not unique (%s).", (*(struct lys_revision**)p)->date);
7976 }
7977 }
7978 }
7979
7980 YIN_EXTCOMPLEX_ENLARGE(struct lys_revision*);
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007981 } else if (!strcmp(node->name, "unique")) {
7982 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_UNIQUE, struct lys_unique*);
7983
7984 *(struct lys_unique**)p = calloc(1, sizeof(struct lys_unique));
7985 if (fill_yin_unique(mod, (struct lys_node*)ext, node, *(struct lys_unique**)p, unres)) {
7986 goto error;
7987 }
7988
7989 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_UNIQUE, i, unres)) {
7990 goto error;
7991 }
7992 YIN_EXTCOMPLEX_ENLARGE(struct lys_unique*);
Radek Krejcif95b6292017-02-13 15:57:37 +01007993 } else if (!strcmp(node->name, "action")) {
7994 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ACTION, read_yin_rpc_action);
7995 } else if (!strcmp(node->name, "anydata")) {
7996 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYDATA, read_yin_anydata, LYS_ANYDATA, 0);
7997 } else if (!strcmp(node->name, "anyxml")) {
7998 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYXML, read_yin_anydata, LYS_ANYXML, 0);
7999 } else if (!strcmp(node->name, "case")) {
8000 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CASE, read_yin_case, 0);
8001 } else if (!strcmp(node->name, "choice")) {
8002 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CHOICE, read_yin_choice, 0);
8003 } else if (!strcmp(node->name, "container")) {
8004 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CONTAINER, read_yin_container, 0);
8005 } else if (!strcmp(node->name, "grouping")) {
8006 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_GROUPING, read_yin_grouping, 0);
8007 } else if (!strcmp(node->name, "output")) {
8008 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_OUTPUT, read_yin_input_output);
8009 } else if (!strcmp(node->name, "input")) {
8010 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_INPUT, read_yin_input_output);
8011 } else if (!strcmp(node->name, "leaf")) {
8012 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAF, read_yin_leaf, 0);
8013 } else if (!strcmp(node->name, "leaf-list")) {
8014 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAFLIST, read_yin_leaflist, 0);
8015 } else if (!strcmp(node->name, "list")) {
8016 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LIST, read_yin_list, 0);
8017 } else if (!strcmp(node->name, "notification")) {
8018 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_NOTIFICATION, read_yin_notif);
8019 } else if (!strcmp(node->name, "uses")) {
8020 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_USES, read_yin_uses);
Radek Krejciaa9c5202017-02-15 16:10:14 +01008021 } else if (!strcmp(node->name, "length")) {
8022 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_LENGTH);
8023 } else if (!strcmp(node->name, "must")) {
8024 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MUST);
8025 if (!pp) {
8026 goto error;
8027 }
8028 /* allocate structure for must */
8029 (*pp) = calloc(1, sizeof(struct lys_restr));
8030
8031 if (fill_yin_must(mod, node, *((struct lys_restr **)pp), unres)) {
8032 goto error;
8033 }
8034 } else if (!strcmp(node->name, "pattern")) {
8035 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_PATTERN, struct lys_restr*);
8036 GETVAL(value, node, "value");
8037 if (lyp_check_pattern(value, NULL)) {
8038 goto error;
8039 }
8040
8041 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr));
8042 (*(struct lys_restr **)p)->expr = lydict_insert(mod->ctx, value, 0);
8043
8044 modifier = 0x06; /* ACK */
8045 if (mod->version >= 2) {
8046 name = NULL;
8047 LY_TREE_FOR(node->child, child) {
8048 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
8049 if (name) {
8050 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
8051 goto error;
8052 }
8053
8054 GETVAL(name, child, "value");
8055 if (!strcmp(name, "invert-match")) {
8056 modifier = 0x15; /* NACK */
8057 } else {
8058 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
8059 goto error;
8060 }
8061 /* get extensions of the modifier */
8062 if (lyp_yin_parse_subnode_ext(mod, *(struct lys_restr **)p, LYEXT_PAR_RESTR, child,
8063 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
8064 goto error;
8065 }
8066 }
8067 }
8068 }
8069
8070 /* store the value: modifier byte + value + terminating NULL byte */
8071 (*(struct lys_restr **)p)->expr = malloc((strlen(value) + 2) * sizeof(char));
8072 ((char *)(*(struct lys_restr **)p)->expr)[0] = modifier;
8073 strcpy(&((char *)(*(struct lys_restr **)p)->expr)[1], value);
8074 lydict_insert_zc(mod->ctx, (char *)(*(struct lys_restr **)p)->expr);
8075
8076 /* get possible sub-statements */
8077 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) {
8078 goto error;
8079 }
8080
8081 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
8082 } else if (!strcmp(node->name, "range")) {
8083 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_RANGE);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008084 } else {
Radek Krejci06a9aa02017-02-17 10:50:24 +01008085 LOGERR(LY_SUCCESS, "Extension's substatement \"%s\" not supported.", node->name);
8086 //LOGERR(LY_EINT, "Extension's substatement \"%s\" not supported.", node->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01008087 //return EXIT_FAILURE;
8088 }
8089 lyxml_free(mod->ctx, node);
8090 }
8091
PavolVicanc4b798e2017-02-20 23:15:27 +01008092 if (ext->substmt && lyp_mand_check_ext(ext, yin->name)) {
8093 return EXIT_FAILURE;
Radek Krejci06a9aa02017-02-17 10:50:24 +01008094 }
8095
Radek Krejci8d6b7422017-02-03 14:42:13 +01008096 return EXIT_SUCCESS;
8097
8098error:
8099 return EXIT_FAILURE;
8100}