blob: a38e633e2e8647fdf9324e84d2c0c5689032c8c4 [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 Krejcifccd1442017-01-16 10:26:57 +0100418read_restr_substmt(struct lys_module *module, LYEXT_PAR restr_type, struct lys_restr *restr, struct lyxml_elem *yin,
419 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 Krejci8d6b7422017-02-03 14:42:13 +0100430 if (lyp_yin_parse_subnode_ext(module, restr, restr_type, 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 Krejci8d6b7422017-02-03 14:42:13 +0100438 if (lyp_yin_parse_subnode_ext(module, restr, restr_type, 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 Krejci8d6b7422017-02-03 14:42:13 +0100450 if (lyp_yin_parse_subnode_ext(module, restr, restr_type, 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 Krejci8d6b7422017-02-03 14:42:13 +0100462 if (lyp_yin_parse_subnode_ext(module, restr, restr_type, 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 Krejci8d6b7422017-02-03 14:42:13 +0100472 if (lyp_yin_parse_subnode_ext(module, restr, restr_type, 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 Krejcifdc0d702017-01-23 15:58:38 +0100839 if (read_restr_substmt(module, LYEXT_PAR_RESTR, 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 Krejcifdc0d702017-01-23 15:58:38 +01001231 if (read_restr_substmt(module, LYEXT_PAR_RESTR, *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 Krejcifdc0d702017-01-23 15:58:38 +01001348 if (read_restr_substmt(module, LYEXT_PAR_RESTR, 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 Krejciac00b2a2017-01-17 14:05:00 +01001394 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001395 return EXIT_FAILURE;
1396 }
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 Krejcifdc0d702017-01-23 15:58:38 +01001411 if (read_restr_substmt(module, LYEXT_PAR_RESTR, 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 Krejcifdc0d702017-01-23 15:58:38 +01001820 return read_restr_substmt(module, LYEXT_PAR_RESTR, 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
Michal Vasko88c29542015-11-27 14:57:53 +01001827fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1828 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001829{
1830 int i, j;
1831 const char *value, *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +02001832 struct unres_list_uniq *unique_info;
Radek Krejci581ce772015-11-10 17:22:40 +01001833
1834 /* get unique value (list of leafs supposed to be unique */
1835 GETVAL(value, yin, "tag");
1836
1837 /* count the number of unique leafs in the value */
1838 vaux = value;
1839 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001840 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001841 while (isspace(*vaux)) {
1842 vaux++;
1843 }
1844 }
1845 unique->expr_size++;
1846 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001847 if (!unique->expr) {
1848 LOGMEM;
1849 goto error;
1850 }
Radek Krejci581ce772015-11-10 17:22:40 +01001851
1852 for (i = 0; i < unique->expr_size; i++) {
1853 vaux = strpbrk(value, " \t\n");
1854 if (!vaux) {
1855 /* the last token, lydict_insert() will count its size on its own */
1856 vaux = value;
1857 }
1858
1859 /* store token into unique structure */
1860 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1861
1862 /* check that the expression does not repeat */
1863 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001864 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001865 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1866 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001867 goto error;
1868 }
1869 }
1870
1871 /* try to resolve leaf */
1872 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001873 unique_info = malloc(sizeof *unique_info);
1874 unique_info->list = parent;
1875 unique_info->expr = unique->expr[i];
1876 unique_info->trg_type = &unique->trg_type;
1877 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1){
Pavol Vican18b10212016-04-11 15:41:52 +02001878 goto error;
1879 }
Radek Krejci581ce772015-11-10 17:22:40 +01001880 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001881 if (resolve_unique(parent, unique->expr[i], &unique->trg_type)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001882 goto error;
1883 }
1884 }
1885
1886 /* move to next token */
1887 value = vaux;
1888 while(isspace(*value)) {
1889 value++;
1890 }
1891 }
1892
1893 return EXIT_SUCCESS;
1894
1895error:
1896 return EXIT_FAILURE;
1897}
1898
Michal Vasko0d343d12015-08-24 14:57:36 +02001899/* logs directly
1900 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001901 * type: 0 - min, 1 - max
1902 */
1903static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001904deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001905{
1906 const char *value;
1907 char *endptr;
1908 unsigned long val;
Pavol Vican09adcc32016-08-25 10:51:36 +02001909 uint32_t *ui32val, *min, *max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001910
Michal Vaskof7e57d52016-03-07 11:31:09 +01001911 /* del min/max is forbidden */
1912 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001913 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001914 goto error;
1915 }
1916
Radek Krejcieb00f512015-07-01 16:44:58 +02001917 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001918 if (target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001919 max = &((struct lys_node_leaflist *)target)->max;
1920 min = &((struct lys_node_leaflist *)target)->min;
Radek Krejci76512572015-08-04 09:47:08 +02001921 } else if (target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001922 max = &((struct lys_node_list *)target)->max;
1923 min = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001924 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001925 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1926 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001927 goto error;
1928 }
1929
1930 GETVAL(value, node, "value");
1931 while (isspace(value[0])) {
1932 value++;
1933 }
1934
Radek Krejci0d7b2472016-02-12 11:11:03 +01001935 if (type && !strcmp(value, "unbounded")) {
1936 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001937 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001938 ui32val = max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001939 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001940 /* convert it to uint32_t */
1941 errno = 0;
1942 endptr = NULL;
1943 val = strtoul(value, &endptr, 10);
1944 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001945 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001946 goto error;
1947 }
1948 if (type) {
1949 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001950 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001951 ui32val = max;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001952 } else {
1953 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001954 d->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001955 ui32val = min;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001956 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001957 }
1958
1959 if (d->mod == LY_DEVIATE_ADD) {
1960 /* check that there is no current value */
1961 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001962 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1963 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001964 goto error;
1965 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001966 } else if (d->mod == LY_DEVIATE_RPL) {
1967 /* unfortunately, there is no way to check reliably that there
1968 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02001969 }
1970
Michal Vaskof7e57d52016-03-07 11:31:09 +01001971 /* add (already checked) and replace */
1972 /* set new value specified in deviation */
1973 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02001974
Pavol Vican09adcc32016-08-25 10:51:36 +02001975 /* check min-elements is smaller than max-elements */
1976 if (*max && *min > *max) {
1977 if (type) {
Radek Krejci73f96012016-10-03 13:53:53 +02001978 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "max-elements");
Pavol Vican09adcc32016-08-25 10:51:36 +02001979 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
1980 } else {
Radek Krejci73f96012016-10-03 13:53:53 +02001981 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "min-elements");
Pavol Vican09adcc32016-08-25 10:51:36 +02001982 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
1983 }
1984 goto error;
1985 }
1986
Radek Krejcieb00f512015-07-01 16:44:58 +02001987 return EXIT_SUCCESS;
1988
1989error:
1990
1991 return EXIT_FAILURE;
1992}
1993
Michal Vasko0d343d12015-08-24 14:57:36 +02001994/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001995static int
Michal Vasko88c29542015-11-27 14:57:53 +01001996fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1997 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001998{
1999 const char *value, **stritem;
Radek Krejcie534c132016-11-23 13:32:31 +01002000 struct lyxml_elem *next, *next2, *child, *develem;
2001 int c_dev = 0, c_must, c_uniq, c_dflt, c_ext = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002002 int f_min = 0, f_max = 0; /* flags */
Radek Krejci6bd2c022017-02-01 15:04:49 +01002003 int i, j, k, rc;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002004 unsigned int u;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002005 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02002006 struct lys_deviate *d = NULL;
Radek Krejcie00d2312016-08-12 15:27:49 +02002007 struct lys_node *node = NULL, *parent, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002008 struct lys_node_choice *choice = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002009 struct lys_node_leaf *leaf = NULL;
2010 struct ly_set *dflt_check = ly_set_new();
Radek Krejcib8048692015-08-05 13:36:34 +02002011 struct lys_node_list *list = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002012 struct lys_node_leaflist *llist = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002013 struct lys_type *t = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002014 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002015 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01002016 struct unres_schema tmp_unres;
Radek Krejci27fe55e2016-09-13 17:13:35 +02002017 struct lys_module *mod;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002018 void *reallocated;
Radek Krejcieb00f512015-07-01 16:44:58 +02002019
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002020 ctx = module->ctx;
2021
Radek Krejcieb00f512015-07-01 16:44:58 +02002022 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002023 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002024 if (!dev->target_name) {
2025 goto error;
2026 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002027
2028 /* resolve target node */
Radek Krejcidf46e222016-11-08 11:57:37 +01002029 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1, (const struct lys_node **)&dev_target);
Michal Vasko60f4b452016-02-12 11:02:55 +01002030 if (rc || !dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002031 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002032 goto error;
2033 }
Radek Krejcic4283442016-04-22 09:19:27 +02002034 if (dev_target->module == lys_main_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002035 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
2036 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002037 goto error;
2038 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002039
2040 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01002041 if (!child->ns ) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002042 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002043 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002044 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01002045 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2046 /* extension */
2047 c_ext++;
2048 continue;
2049 } else if (!strcmp(child->name, "description")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002050 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002051 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002052 goto error;
2053 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002054 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002055 goto error;
2056 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002057 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002058 if (!dev->dsc) {
2059 goto error;
2060 }
2061 } else if (!strcmp(child->name, "reference")) {
2062 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002063 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002064 goto error;
2065 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002066 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002067 goto error;
2068 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002069 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002070 if (!dev->ref) {
2071 goto error;
2072 }
2073 } else if (!strcmp(child->name, "deviate")) {
2074 c_dev++;
2075
Michal Vasko345da0a2015-12-02 10:35:55 +01002076 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02002077 * further processed later
2078 */
2079 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02002080
Radek Krejcieb00f512015-07-01 16:44:58 +02002081 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002082 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002083 goto error;
2084 }
2085
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002086 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02002087 }
2088
2089 if (c_dev) {
2090 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01002091 if (!dev->deviate) {
2092 LOGMEM;
2093 goto error;
2094 }
Pavol Vican09adcc32016-08-25 10:51:36 +02002095 } else {
2096 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
2097 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002098 }
Radek Krejcie534c132016-11-23 13:32:31 +01002099 if (c_ext) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002100 /* some extensions may be already present from the substatements */
2101 reallocated = realloc(dev->ext, (c_ext + dev->ext_size) * sizeof *dev->ext);
2102 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01002103 LOGMEM;
2104 goto error;
2105 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002106 dev->ext = reallocated;
Radek Krejcieb00f512015-07-01 16:44:58 +02002107
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002108 /* init memory */
2109 memset(&dev->ext[dev->ext_size], 0, c_ext * sizeof *dev->ext);
2110 }
Radek Krejcie534c132016-11-23 13:32:31 +01002111
2112 LY_TREE_FOR_SAFE(yin->child, next, develem) {
2113 if (strcmp(develem->ns->value, LY_NSYIN)) {
2114 /* deviation's extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01002115 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 +01002116 dev->ext_size++;
2117 if (rc) {
2118 goto error;
2119 }
2120 continue;
2121 }
2122
2123 /* deviate */
Radek Krejcieb00f512015-07-01 16:44:58 +02002124 /* init */
2125 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002126 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002127 c_must = 0;
2128 c_uniq = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002129 c_dflt = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01002130 c_ext = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002131
2132 /* get deviation type */
2133 GETVAL(value, develem, "value");
2134 if (!strcmp(value, "not-supported")) {
2135 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002136 /* no other deviate statement is expected,
Radek Krejci5b917642015-07-02 09:03:13 +02002137 * not-supported deviation must be the only deviation of the target
2138 */
2139 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002140 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2141 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02002142 goto error;
2143 }
2144
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002145 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02002146 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
2147 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
2148 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002149 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2150 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002151 goto error;
2152 }
2153 }
2154 }
Radek Krejci5b917642015-07-02 09:03:13 +02002155
Michal Vaskoff006c12016-02-17 11:15:19 +01002156 /* unlink and store the original node */
Radek Krejci30bfcd22017-01-27 16:54:48 +01002157 parent = dev_target->parent;
Michal Vaskoff006c12016-02-17 11:15:19 +01002158 lys_node_unlink(dev_target);
Radek Krejci30bfcd22017-01-27 16:54:48 +01002159 if (parent && parent->nodetype == LYS_AUGMENT) {
2160 /* hack for augment, because when the original will be sometime reconnected back, we actually need
2161 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
2162 * path), so we need to remember the augment as an addition */
2163 dev_target->parent = parent;
2164 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002165 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02002166
Radek Krejcieb00f512015-07-01 16:44:58 +02002167 } else if (!strcmp(value, "add")) {
2168 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
2169 } else if (!strcmp(value, "replace")) {
2170 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
2171 } else if (!strcmp(value, "delete")) {
2172 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
2173 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002174 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002175 goto error;
2176 }
2177 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01002178 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002179
Michal Vaskoff006c12016-02-17 11:15:19 +01002180 /* store a shallow copy of the original node */
2181 if (!dev->orig_node) {
2182 memset(&tmp_unres, 0, sizeof tmp_unres);
Radek Krejci6ff885d2017-01-03 14:06:22 +01002183 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, &tmp_unres, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01002184 /* just to be safe */
2185 if (tmp_unres.count) {
2186 LOGINT;
2187 goto error;
2188 }
2189 }
2190
Radek Krejcieb00f512015-07-01 16:44:58 +02002191 /* process deviation properties */
Radek Krejcie534c132016-11-23 13:32:31 +01002192 LY_TREE_FOR_SAFE(develem->child, next2, child) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002193 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002194 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002195 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002196 continue;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002197 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2198 /* extensions */
2199 c_ext++;
2200 } else if (d->mod == LY_DEVIATE_NO) {
2201 /* no YIN substatement expected in this case */
2202 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2203 goto error;
2204 } else if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002205 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002206 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002207 goto error;
2208 }
2209
2210 /* for we deviate from RFC 6020 and allow config property even it is/is not
2211 * specified in the target explicitly since config property inherits. So we expect
2212 * that config is specified in every node. But for delete, we check that the value
2213 * is the same as here in deviation
2214 */
2215 GETVAL(value, child, "value");
2216 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002217 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02002218 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002219 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02002220 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002221 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002222 goto error;
2223 }
2224
2225 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002226 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002227 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002228 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002229 } else { /* add and replace are the same in this case */
2230 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01002231 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002232
2233 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01002234 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002235 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002236
Radek Krejci8d6b7422017-02-03 14:42:13 +01002237 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002238 goto error;
2239 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002240 } else if (!strcmp(child->name, "default")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002241 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 +01002242 goto error;
2243 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002244 c_dflt++;
2245
2246 /* check target node type */
2247 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
2248 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2249 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
2250 goto error;
2251 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
2252 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2253 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
2254 goto error;
2255 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
2256 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2257 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002258 goto error;
2259 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002260
Radek Krejcid5a5c282016-08-15 15:38:08 +02002261 /* skip lyxml_free() at the end of the loop, this node will be processed later */
2262 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02002263
Radek Krejcieb00f512015-07-01 16:44:58 +02002264 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002265 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002266 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002267 goto error;
2268 }
2269
2270 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002271 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002272 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2273 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002274 goto error;
2275 }
2276
2277 GETVAL(value, child, "value");
2278 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002279 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002280 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002281 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002282 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002283 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002284 goto error;
2285 }
2286
2287 if (d->mod == LY_DEVIATE_ADD) {
2288 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01002289 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002290 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2291 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002292 goto error;
2293 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002294
Radek Krejci841ec082016-04-05 13:05:17 +02002295 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02002296 if (d->flags & LYS_MAND_TRUE) {
2297 if (dev_target->nodetype == LYS_CHOICE) {
2298 if (((struct lys_node_choice *)(dev_target))->dflt) {
2299 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2300 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2301 "Adding the \"mandatory\" statement is forbidden on choice with the \"default\" statement.");
2302 goto error;
2303 }
2304 } else if (dev_target->nodetype == LYS_LEAF) {
2305 if (((struct lys_node_leaf *)(dev_target))->dflt) {
2306 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2307 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2308 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
2309 goto error;
2310 }
2311 }
Radek Krejci841ec082016-04-05 13:05:17 +02002312 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002313
Michal Vasko21be1b32016-03-07 12:31:34 +01002314 dev_target->flags |= d->flags & LYS_MAND_MASK;
2315 } else if (d->mod == LY_DEVIATE_RPL) {
2316 /* check that there was a value before */
2317 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002318 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2319 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002320 goto error;
2321 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002322
Michal Vasko21be1b32016-03-07 12:31:34 +01002323 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01002324 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01002325 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002326 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002327 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002328 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002329 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002330
2331 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2332 for (parent = dev_target->parent;
2333 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2334 parent = parent->parent) {
2335 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2336 /* stop also on presence containers */
2337 break;
2338 }
2339 }
2340 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2341 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2342 if (lyp_check_mandatory_choice(parent)) {
2343 goto error;
2344 }
2345 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002346
Radek Krejci8d6b7422017-02-03 14:42:13 +01002347 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002348 goto error;
2349 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002350 } else if (!strcmp(child->name, "min-elements")) {
2351 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002352 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002353 goto error;
2354 }
2355 f_min = 1;
2356
Michal Vasko60f4b452016-02-12 11:02:55 +01002357 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002358 goto error;
2359 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002360 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002361 goto error;
2362 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002363 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002364 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002365 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002366 goto error;
2367 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01002368 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02002369
Michal Vasko60f4b452016-02-12 11:02:55 +01002370 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002371 goto error;
2372 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002373 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002374 goto error;
2375 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002376 } else if (!strcmp(child->name, "must")) {
2377 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002378 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002379 continue;
2380 } else if (!strcmp(child->name, "type")) {
2381 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002382 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002383 goto error;
2384 }
2385
Michal Vaskof7e57d52016-03-07 11:31:09 +01002386 /* add, del type is forbidden */
2387 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002388 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002389 goto error;
2390 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002391 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002392 goto error;
2393 }
2394
Radek Krejcieb00f512015-07-01 16:44:58 +02002395 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002396 if (dev_target->nodetype == LYS_LEAF) {
2397 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002398 if (((struct lys_node_leaf *)dev_target)->dflt) {
2399 ly_set_add(dflt_check, dev_target, 0);
2400 }
Michal Vasko60f4b452016-02-12 11:02:55 +01002401 } else if (dev_target->nodetype == LYS_LEAFLIST) {
2402 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002403 if (((struct lys_node_leaflist *)dev_target)->dflt) {
2404 ly_set_add(dflt_check, dev_target, 0);
2405 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002406 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002407 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2408 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002409 goto error;
2410 }
2411
Radek Krejcieb00f512015-07-01 16:44:58 +02002412 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002413 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01002414 /* HACK for unres */
2415 t->der = (struct lys_tpdf *)child;
Michal Vasko3767fb22016-07-21 12:10:57 +02002416 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002417 goto error;
2418 }
2419 d->type = t;
2420 } else if (!strcmp(child->name, "unique")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002421 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 +01002422 goto error;
2423 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002424 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002425 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002426 continue;
2427 } else if (!strcmp(child->name, "units")) {
2428 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002429 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002430 goto error;
2431 }
2432
2433 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002434 if (dev_target->nodetype == LYS_LEAFLIST) {
2435 stritem = &((struct lys_node_leaflist *)dev_target)->units;
2436 } else if (dev_target->nodetype == LYS_LEAF) {
2437 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02002438 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002439 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2440 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002441 goto error;
2442 }
2443
2444 /* get units value */
2445 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002446 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02002447
2448 /* apply to target */
2449 if (d->mod == LY_DEVIATE_ADD) {
2450 /* check that there is no current value */
2451 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002452 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2453 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002454 goto error;
2455 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002456
Michal Vasko21be1b32016-03-07 12:31:34 +01002457 *stritem = lydict_insert(ctx, value, 0);
2458 } else if (d->mod == LY_DEVIATE_RPL) {
2459 /* check that there was a value before */
2460 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002461 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2462 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01002463 goto error;
2464 }
2465
2466 lydict_remove(ctx, *stritem);
2467 *stritem = lydict_insert(ctx, value, 0);
2468 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002469 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002470 if (!ly_strequal(*stritem, d->units, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002471 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2472 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002473 goto error;
2474 }
2475 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002476 lydict_remove(ctx, *stritem);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002477 (*stritem) = NULL;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002478
2479 /* remove its extensions */
2480 j = -1;
2481 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_UNITS)) != -1) {
2482 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2483 --j;
2484 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002485 }
2486
Radek Krejci8d6b7422017-02-03 14:42:13 +01002487 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002488 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002489 }
2490 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002491 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002492 goto error;
2493 }
2494
Michal Vasko88c29542015-11-27 14:57:53 +01002495 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002496 }
2497
2498 if (c_must) {
2499 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002500 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002501 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002502 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2503 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002504 break;
Radek Krejci76512572015-08-04 09:47:08 +02002505 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002506 trg_must = &((struct lys_node_container *)dev_target)->must;
2507 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002508 break;
Radek Krejci76512572015-08-04 09:47:08 +02002509 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002510 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2511 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002512 break;
Radek Krejci76512572015-08-04 09:47:08 +02002513 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002514 trg_must = &((struct lys_node_list *)dev_target)->must;
2515 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002516 break;
Radek Krejci76512572015-08-04 09:47:08 +02002517 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002518 case LYS_ANYDATA:
2519 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2520 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002521 break;
2522 default:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002523 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2524 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002525 goto error;
2526 }
2527
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002528 dev_target->flags &= ~LYS_XPATH_DEP;
Michal Vasko508a50d2016-09-07 14:50:33 +02002529
Radek Krejcieb00f512015-07-01 16:44:58 +02002530 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002531 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002532 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002533 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002534 } else if (d->mod == LY_DEVIATE_ADD) {
2535 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002536 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002537 if (!d->must) {
2538 LOGMEM;
2539 goto error;
2540 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002541 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02002542 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002543 d->must_size = c_must;
2544 } else { /* LY_DEVIATE_DEL */
2545 d->must = calloc(c_must, sizeof *d->must);
2546 }
Michal Vasko253035f2015-12-17 16:58:13 +01002547 if (!d->must) {
2548 LOGMEM;
2549 goto error;
2550 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002551 }
2552 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002553 /* replace unique is forbidden */
2554 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002555 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002556 goto error;
2557 }
2558
Radek Krejcieb00f512015-07-01 16:44:58 +02002559 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002560 if (dev_target->nodetype != LYS_LIST) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002561 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2562 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002563 goto error;
2564 }
2565
Michal Vasko60f4b452016-02-12 11:02:55 +01002566 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002567 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002568 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002569 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02002570 list->unique = d->unique;
2571 d->unique = &list->unique[list->unique_size];
2572 d->unique_size = c_uniq;
2573 } else { /* LY_DEVIATE_DEL */
2574 d->unique = calloc(c_uniq, sizeof *d->unique);
2575 }
Michal Vasko253035f2015-12-17 16:58:13 +01002576 if (!d->unique) {
2577 LOGMEM;
2578 goto error;
2579 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002580 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002581 if (c_dflt) {
2582 if (d->mod == LY_DEVIATE_ADD) {
2583 /* check that there is no current value */
2584 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
2585 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
2586 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2587 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
2588 goto error;
2589 }
2590
2591 /* check collision with mandatory/min-elements */
2592 if ((dev_target->flags & LYS_MAND_TRUE) ||
2593 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
2594 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2595 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2596 "Adding the \"default\" statement is forbidden on %s statement.",
2597 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2598 goto error;
2599 }
2600 } else if (d->mod == LY_DEVIATE_RPL) {
2601 /* check that there was a value before */
2602 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2603 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
2604 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2605 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
2606 goto error;
2607 }
2608 }
2609
2610 if (dev_target->nodetype == LYS_LEAFLIST) {
2611 /* reallocate default list in the target */
2612 llist = (struct lys_node_leaflist *)dev_target;
2613 if (d->mod == LY_DEVIATE_ADD) {
2614 /* reallocate (enlarge) the unique array of the target */
2615 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
2616 } else if (d->mod == LY_DEVIATE_RPL) {
2617 /* reallocate (replace) the unique array of the target */
2618 for (i = 0; i < llist->dflt_size; i++) {
2619 lydict_remove(llist->module->ctx, llist->dflt[i]);
2620 }
2621 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2622 llist->dflt_size = 0;
2623 }
2624 }
2625 d->dflt = calloc(c_dflt, sizeof *d->dflt);
2626 if (!d->dflt) {
2627 LOGMEM;
2628 goto error;
2629 }
2630 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002631 if (c_ext) {
2632 /* some extensions may be already present from the substatements */
2633 reallocated = realloc(d->ext, (c_ext + d->ext_size) * sizeof *d->ext);
2634 if (!reallocated) {
2635 LOGMEM;
2636 goto error;
2637 }
2638 d->ext = reallocated;
2639
2640 /* init memory */
2641 memset(&d->ext[d->ext_size], 0, c_ext * sizeof *d->ext);
2642 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002643
2644 /* process deviation properties with 0..n cardinality */
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002645 LY_TREE_FOR_SAFE(develem->child, next2, child) {
2646 if (strcmp(child->ns->value, LY_NSYIN)) {
2647 /* extension */
2648 if (lyp_yin_fill_ext(d, LYEXT_PAR_DEVIATE, 0, 0, module, child, &d->ext, d->ext_size, unres)) {
2649 goto error;
2650 }
2651 d->ext_size++;
2652 } else if (!strcmp(child->name, "must")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002653 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcifccd1442017-01-16 10:26:57 +01002654 if (fill_yin_must(module, child, &d->must[d->must_size], unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002655 goto error;
2656 }
2657
2658 /* find must to delete, we are ok with just matching conditions */
2659 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002660 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002661 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002662 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02002663 /* ... and maintain the array */
2664 (*trg_must_size)--;
2665 if (i != *trg_must_size) {
2666 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2667 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2668 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2669 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2670 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2671 }
2672 if (!(*trg_must_size)) {
2673 free(*trg_must);
2674 *trg_must = NULL;
2675 } else {
2676 (*trg_must)[*trg_must_size].expr = NULL;
2677 (*trg_must)[*trg_must_size].dsc = NULL;
2678 (*trg_must)[*trg_must_size].ref = NULL;
2679 (*trg_must)[*trg_must_size].eapptag = NULL;
2680 (*trg_must)[*trg_must_size].emsg = NULL;
2681 }
2682
2683 i = -1; /* set match flag */
2684 break;
2685 }
2686 }
2687 d->must_size++;
2688 if (i != -1) {
2689 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002690 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002691 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01002692 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002693 goto error;
2694 }
2695 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002696 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
Radek Krejcifccd1442017-01-16 10:26:57 +01002697 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]), unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002698 goto error;
2699 }
2700 (*trg_must_size)++;
2701 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002702
2703 /* check XPath dependencies again */
Michal Vaskoe8734262016-09-29 14:12:06 +02002704 if (*trg_must_size && unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02002705 goto error;
2706 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002707 } else if (!strcmp(child->name, "unique")) {
2708 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002709 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002710 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002711 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002712 goto error;
2713 }
2714
2715 /* find unique structures to delete */
2716 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002717 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002718 continue;
2719 }
2720
Radek Krejci581ce772015-11-10 17:22:40 +01002721 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002722 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002723 break;
2724 }
2725 }
2726
Radek Krejci581ce772015-11-10 17:22:40 +01002727 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002728 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002729 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002730 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002731 }
2732 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002733 /* ... and maintain the array */
2734 list->unique_size--;
2735 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002736 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2737 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002738 }
2739
2740 if (!list->unique_size) {
2741 free(list->unique);
2742 list->unique = NULL;
2743 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002744 list->unique[list->unique_size].expr_size = 0;
2745 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002746 }
2747
Radek Krejci6bd2c022017-02-01 15:04:49 +01002748 k = i; /* remember index for removing extensions */
Radek Krejcieb00f512015-07-01 16:44:58 +02002749 i = -1; /* set match flag */
2750 break;
2751 }
2752 }
2753
2754 d->unique_size++;
2755 if (i != -1) {
2756 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002757 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2758 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002759 goto error;
2760 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01002761
2762 /* remove extensions of this unique instance from the target node */
2763 j = -1;
2764 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 +01002765 if (dev_target->ext[j]->insubstmt_index == k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002766 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2767 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01002768 } else if (dev_target->ext[j]->insubstmt_index > k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002769 /* decrease the substatement index of the extension because of the changed array of uniques */
Radek Krejcifebdad72017-02-06 11:35:51 +01002770 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002771 }
2772 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002773 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002774 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002775 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002776 list->unique_size++;
2777 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002778 goto error;
2779 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002780 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002781 } else if (!strcmp(child->name, "default")) {
2782 GETVAL(value, child, "value");
2783 u = strlen(value);
2784 d->dflt[d->dflt_size++] = lydict_insert(module->ctx, value, u);
2785
2786 if (dev_target->nodetype == LYS_CHOICE) {
2787 choice = (struct lys_node_choice *)dev_target;
2788 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2789 if (rc || !node) {
2790 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2791 goto error;
2792 }
2793 if (d->mod == LY_DEVIATE_DEL) {
2794 if (!choice->dflt || (choice->dflt != node)) {
2795 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2796 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2797 goto error;
2798 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01002799 choice->dflt = NULL;
2800 /* remove extensions of this default instance from the target node */
2801 j = -1;
2802 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
2803 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2804 --j;
2805 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002806 } else { /* add or replace */
2807 choice->dflt = node;
2808 if (!choice->dflt) {
2809 /* default branch not found */
2810 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2811 goto error;
2812 }
2813 }
2814 } else if (dev_target->nodetype == LYS_LEAF) {
2815 leaf = (struct lys_node_leaf *)dev_target;
2816 if (d->mod == LY_DEVIATE_DEL) {
2817 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
2818 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2819 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2820 goto error;
2821 }
2822 /* remove value */
2823 lydict_remove(ctx, leaf->dflt);
2824 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01002825 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002826
2827 /* remove extensions of this default instance from the target node */
2828 j = -1;
2829 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
2830 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2831 --j;
2832 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002833 } else { /* add (already checked) and replace */
2834 /* remove value */
2835 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01002836 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002837
2838 /* set new value */
2839 leaf->dflt = lydict_insert(ctx, value, u);
2840
Radek Krejcibd117f02016-11-04 16:28:08 +01002841 /* remember to check it later (it may not fit now, because the type can be deviated too) */
Radek Krejcid5a5c282016-08-15 15:38:08 +02002842 ly_set_add(dflt_check, dev_target, 0);
2843 }
2844 } else { /* LYS_LEAFLIST */
2845 llist = (struct lys_node_leaflist *)dev_target;
2846 if (d->mod == LY_DEVIATE_DEL) {
2847 /* find and remove the value in target list */
2848 for (i = 0; i < llist->dflt_size; i++) {
2849 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
2850 /* match, remove the value */
2851 lydict_remove(llist->module->ctx, llist->dflt[i]);
2852 llist->dflt[i] = NULL;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002853
2854 /* remove extensions of this default instance from the target node */
2855 j = -1;
2856 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 +01002857 if (dev_target->ext[j]->insubstmt_index == i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002858 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2859 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01002860 } else if (dev_target->ext[j]->insubstmt_index > i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002861 /* decrease the substatement index of the extension because of the changed array of defaults */
Radek Krejcifebdad72017-02-06 11:35:51 +01002862 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002863 }
2864 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002865 break;
2866 }
2867 }
2868 if (i == llist->dflt_size) {
2869 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2870 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
2871 goto error;
2872 }
2873 } else {
2874 /* add or replace, anyway we place items into the deviate's list
2875 which propagates to the target */
2876 /* we just want to check that the value isn't already in the list */
2877 for (i = 0; i < llist->dflt_size; i++) {
2878 if (ly_strequal(llist->dflt[i], value, 1)) {
2879 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2880 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2881 goto error;
2882 }
2883 }
2884 /* store it in target node */
2885 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, u);
2886
2887 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2888 ly_set_add(dflt_check, dev_target, 0);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002889 llist->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002890 }
2891 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002892 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002893 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002894
2895 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
2896 /* consolidate the final list in the target after removing items from it */
2897 llist = (struct lys_node_leaflist *)dev_target;
2898 for (i = j = 0; j < llist->dflt_size; j++) {
2899 llist->dflt[i] = llist->dflt[j];
2900 if (llist->dflt[i]) {
2901 i++;
2902 }
2903 }
2904 llist->dflt_size = i + 1;
2905 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002906 }
2907
Michal Vasko43a1feb2016-03-07 12:03:02 +01002908 /* now check whether default value, if any, matches the type */
Pavol Vican85991ec2016-08-16 14:58:12 +02002909 for (u = 0; u < dflt_check->number; ++u) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002910 value = NULL;
2911 rc = EXIT_SUCCESS;
2912 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2913 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
Radek Krejci51673202016-11-01 17:00:32 +01002914 value = leaf->dflt;
2915 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002916 } else { /* LYS_LEAFLIST */
2917 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2918 for (j = 0; j < llist->dflt_size; j++) {
Radek Krejci51673202016-11-01 17:00:32 +01002919 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2920 (struct lys_node *)(&llist->dflt[j]));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002921 if (rc == -1) {
Radek Krejci51673202016-11-01 17:00:32 +01002922 value = llist->dflt[j];
Radek Krejcid5a5c282016-08-15 15:38:08 +02002923 break;
2924 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002925 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002926
2927 }
2928 if (rc == -1) {
2929 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2930 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2931 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2932 dev->target_name);
2933 goto error;
Michal Vasko43a1feb2016-03-07 12:03:02 +01002934 }
2935 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002936
Radek Krejci27fe55e2016-09-13 17:13:35 +02002937 /* mark all the affected modules as deviated and implemented */
2938 for(parent = dev_target; parent; parent = lys_parent(parent)) {
2939 mod = lys_node_module(parent);
2940 if (module != mod) {
2941 mod->deviated = 1;
2942 lys_set_implemented(mod);
2943 }
2944 }
2945
Radek Krejcid5a5c282016-08-15 15:38:08 +02002946 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002947 return EXIT_SUCCESS;
2948
2949error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002950 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002951 return EXIT_FAILURE;
2952}
2953
Michal Vasko0d343d12015-08-24 14:57:36 +02002954/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002955static int
Radek Krejcib8048692015-08-05 13:36:34 +02002956fill_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 +02002957 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02002958{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002959 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01002960 struct lyxml_elem *sub, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002961 struct lys_node *node;
Radek Krejcie534c132016-11-23 13:32:31 +01002962 int ret, c_ftrs = 0, c_ext = 0;
Radek Krejci30701b42017-01-23 16:41:38 +01002963 void *reallocated;
Radek Krejci106efc02015-06-10 14:36:27 +02002964
Michal Vasko591e0b22015-08-13 13:53:43 +02002965 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002966 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002967 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02002968 if (!aug->target_name) {
2969 goto error;
2970 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002971 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02002972
Radek Krejci07d0fb92017-01-13 14:11:05 +01002973 if (read_yin_common(module, NULL, aug, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002974 goto error;
2975 }
2976
Radek Krejcie534c132016-11-23 13:32:31 +01002977 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2978 if (strcmp(sub->ns->value, LY_NSYIN)) {
2979 /* extension */
2980 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02002981 continue;
Radek Krejci30701b42017-01-23 16:41:38 +01002982 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejcie534c132016-11-23 13:32:31 +01002983 c_ftrs++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002984 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01002985 } else if (!strcmp(sub->name, "when")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002986 if (aug->when) {
Radek Krejcie534c132016-11-23 13:32:31 +01002987 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002988 goto error;
2989 }
2990
Radek Krejci5323b492017-01-16 15:40:11 +01002991 aug->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002992 if (!aug->when) {
Radek Krejcie534c132016-11-23 13:32:31 +01002993 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002994 goto error;
2995 }
Radek Krejcie534c132016-11-23 13:32:31 +01002996 lyxml_free(module->ctx, sub);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002997 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002998
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002999 /* check allowed data sub-statements */
Radek Krejcie534c132016-11-23 13:32:31 +01003000 } else if (!strcmp(sub->name, "container")) {
3001 node = read_yin_container(module, (struct lys_node *)aug, sub, 1, unres);
3002 } else if (!strcmp(sub->name, "leaf-list")) {
3003 node = read_yin_leaflist(module, (struct lys_node *)aug, sub, 1, unres);
3004 } else if (!strcmp(sub->name, "leaf")) {
3005 node = read_yin_leaf(module, (struct lys_node *)aug, sub, 1, unres);
3006 } else if (!strcmp(sub->name, "list")) {
3007 node = read_yin_list(module, (struct lys_node *)aug, sub, 1, unres);
3008 } else if (!strcmp(sub->name, "uses")) {
3009 node = read_yin_uses(module, (struct lys_node *)aug, sub, unres);
3010 } else if (!strcmp(sub->name, "choice")) {
3011 node = read_yin_choice(module, (struct lys_node *)aug, sub, 1, unres);
3012 } else if (!strcmp(sub->name, "case")) {
3013 node = read_yin_case(module, (struct lys_node *)aug, sub, 1, unres);
3014 } else if (!strcmp(sub->name, "anyxml")) {
3015 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYXML, 1, unres);
3016 } else if (!strcmp(sub->name, "anydata")) {
3017 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYDATA, 1, unres);
3018 } else if (!strcmp(sub->name, "action")) {
3019 node = read_yin_rpc_action(module, (struct lys_node *)aug, sub, unres);
3020 } else if (!strcmp(sub->name, "notification")) {
3021 node = read_yin_notif(module, (struct lys_node *)aug, sub, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003022 } else {
Radek Krejcie534c132016-11-23 13:32:31 +01003023 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003024 goto error;
3025 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003026
Radek Krejci1d82ef62015-08-07 14:44:40 +02003027 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003028 goto error;
3029 }
3030
Radek Krejci1d82ef62015-08-07 14:44:40 +02003031 node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01003032 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003033 }
3034
Radek Krejcie534c132016-11-23 13:32:31 +01003035 if (c_ftrs) {
3036 aug->iffeature = calloc(c_ftrs, sizeof *aug->iffeature);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003037 if (!aug->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003038 LOGMEM;
3039 goto error;
3040 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003041 }
Radek Krejcie534c132016-11-23 13:32:31 +01003042 if (c_ext) {
Radek Krejci30701b42017-01-23 16:41:38 +01003043 /* some extensions may be already present from the substatements */
3044 reallocated = realloc(aug->ext, (c_ext + aug->ext_size) * sizeof *aug->ext);
3045 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003046 LOGMEM;
3047 goto error;
3048 }
Radek Krejci30701b42017-01-23 16:41:38 +01003049 aug->ext = reallocated;
3050
3051 /* init memory */
3052 memset(&aug->ext[aug->ext_size], 0, c_ext * sizeof *aug->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003053 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003054
Radek Krejcie534c132016-11-23 13:32:31 +01003055 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3056 if (strcmp(sub->ns->value, LY_NSYIN)) {
3057 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003058 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 +01003059 aug->ext_size++;
3060 if (ret) {
3061 goto error;
3062 }
3063 } else if (!strcmp(sub->name, "if-feature")) {
3064 ret = fill_yin_iffeature((struct lys_node *)aug, 0, sub, &aug->iffeature[aug->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003065 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003066 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003067 goto error;
3068 }
Radek Krejcie534c132016-11-23 13:32:31 +01003069 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003070 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003071 }
3072
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003073 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02003074 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02003075 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02003076 * when the uses does and cannot be resolved now for sure
3077 * (the grouping was not yet copied into uses).
3078 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02003079 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003080 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02003081 goto error;
3082 }
Michal Vasko49291b32015-08-06 09:49:41 +02003083 }
Radek Krejci106efc02015-06-10 14:36:27 +02003084
Michal Vasko508a50d2016-09-07 14:50:33 +02003085 /* check XPath dependencies */
3086 if (aug->when && (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1)) {
3087 goto error;
3088 }
3089
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003090 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02003091
3092error:
3093
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003094 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02003095}
3096
Michal Vasko0d343d12015-08-24 14:57:36 +02003097/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003098static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02003099fill_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 +02003100{
Radek Krejci363bd4a2016-07-29 14:30:20 +02003101 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003102 struct lyxml_elem *sub, *next;
3103 const char *value;
3104 char *endptr;
3105 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01003106 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003107 int r;
3108 unsigned long int val;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003109 void *reallocated;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003110
Radek Krejci363bd4a2016-07-29 14:30:20 +02003111 assert(uses);
3112 module = uses->module; /* shorthand */
3113
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003114 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003115 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02003116 if (!rfn->target_name) {
3117 goto error;
3118 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003119
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003120 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003121 if (!sub->ns) {
3122 /* garbage */
3123 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01003124 /* extension */
3125 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003126 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02003127
Radek Krejci411b1bf2017-01-23 16:40:05 +01003128 } else if (!strcmp(sub->name, "description")) {
3129 if (rfn->dsc) {
3130 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3131 goto error;
3132 }
3133
Radek Krejci8d6b7422017-02-03 14:42:13 +01003134 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003135 goto error;
3136 }
3137
3138 rfn->dsc = read_yin_subnode(module->ctx, sub, "text");
3139 if (!rfn->dsc) {
3140 goto error;
3141 }
3142 } else if (!strcmp(sub->name, "reference")) {
3143 if (rfn->ref) {
3144 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3145 goto error;
3146 }
3147
Radek Krejci8d6b7422017-02-03 14:42:13 +01003148 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003149 goto error;
3150 }
3151
3152 rfn->ref = read_yin_subnode(module->ctx, sub, "text");
3153 if (!rfn->ref) {
3154 goto error;
3155 }
3156 } else if (!strcmp(sub->name, "config")) {
3157 if (rfn->flags & LYS_CONFIG_MASK) {
3158 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3159 goto error;
3160 }
3161 GETVAL(value, sub, "value");
3162 if (!strcmp(value, "false")) {
3163 rfn->flags |= LYS_CONFIG_R;
3164 } else if (!strcmp(value, "true")) {
3165 rfn->flags |= LYS_CONFIG_W;
3166 } else {
3167 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3168 goto error;
3169 }
3170 rfn->flags |= LYS_CONFIG_SET;
3171
Radek Krejci8d6b7422017-02-03 14:42:13 +01003172 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003173 goto error;
3174 }
Radek Krejcie534c132016-11-23 13:32:31 +01003175 } else if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02003176 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02003177
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003178 /* check possibility of statements combination */
3179 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02003180 if (c_dflt) {
3181 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003182 if (module->version < 2) {
3183 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3184 goto error;
3185 }
Radek Krejci200bf712016-08-16 17:11:04 +02003186 rfn->target_type &= LYS_LEAFLIST;
3187 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003188 if (module->version < 2) {
3189 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
3190 } else {
3191 /* YANG 1.1 */
3192 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
3193 }
Radek Krejci200bf712016-08-16 17:11:04 +02003194 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003195 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003196 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3197 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003198 goto error;
3199 }
3200 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003201 if (module->version < 2) {
3202 rfn->target_type = LYS_LEAF | LYS_CHOICE;
3203 } else {
3204 /* YANG 1.1 */
3205 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
3206 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003207 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003208
Radek Krejci8d6b7422017-02-03 14:42:13 +01003209 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 +01003210 goto error;
3211 }
Radek Krejci200bf712016-08-16 17:11:04 +02003212 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003213 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003214 } else if (!strcmp(sub->name, "mandatory")) {
3215 /* leaf, choice or anyxml */
3216 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003217 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003218 goto error;
3219 }
3220 /* just checking the flags in leaf is not sufficient, we would allow
3221 * multiple mandatory statements with the "false" value
3222 */
3223 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003224
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003225 /* check possibility of statements combination */
3226 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003227 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003228 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003229 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3230 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003231 goto error;
3232 }
3233 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003234 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003235 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003237 GETVAL(value, sub, "value");
3238 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003239 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003240 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003241 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003242 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003243 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003244 goto error;
3245 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003246 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003247 goto error;
3248 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003249 } else if (!strcmp(sub->name, "min-elements")) {
3250 /* list or leaf-list */
3251 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003252 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003253 goto error;
3254 }
3255 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003257 /* check possibility of statements combination */
3258 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003259 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003260 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003261 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3262 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003263 goto error;
3264 }
3265 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003266 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003267 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003268
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003269 GETVAL(value, sub, "value");
3270 while (isspace(value[0])) {
3271 value++;
3272 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003273
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003274 /* convert it to uint32_t */
3275 errno = 0;
3276 endptr = NULL;
3277 val = strtoul(value, &endptr, 10);
3278 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003279 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003280 goto error;
3281 }
3282 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003283 rfn->flags |= LYS_RFN_MINSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003284
Radek Krejci8d6b7422017-02-03 14:42:13 +01003285 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003286 goto error;
3287 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003288 } else if (!strcmp(sub->name, "max-elements")) {
3289 /* list or leaf-list */
3290 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003291 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003292 goto error;
3293 }
3294 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003295
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003296 /* check possibility of statements combination */
3297 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003298 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003299 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003300 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3301 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003302 goto error;
3303 }
3304 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003305 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003306 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003307
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003308 GETVAL(value, sub, "value");
3309 while (isspace(value[0])) {
3310 value++;
3311 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003312
Radek Krejci0d7b2472016-02-12 11:11:03 +01003313 if (!strcmp(value, "unbounded")) {
3314 rfn->mod.list.max = 0;
3315 } else {
3316 /* convert it to uint32_t */
3317 errno = 0;
3318 endptr = NULL;
3319 val = strtoul(value, &endptr, 10);
3320 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003321 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003322 goto error;
3323 }
3324 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003325 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003326 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003327
Radek Krejci8d6b7422017-02-03 14:42:13 +01003328 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003329 goto error;
3330 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003331 } else if (!strcmp(sub->name, "presence")) {
3332 /* container */
3333 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003334 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003335 goto error;
3336 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003337
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003338 /* check possibility of statements combination */
3339 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003340 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003341 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003342 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3343 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003344 goto error;
3345 }
3346 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003347 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003348 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003349
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003350 GETVAL(value, sub, "value");
3351 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcifdc0d702017-01-23 15:58:38 +01003352
Radek Krejci8d6b7422017-02-03 14:42:13 +01003353 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003354 goto error;
3355 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003356 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02003357 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003358 /* check possibility of statements combination */
3359 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003360 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003361 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003362 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3363 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003364 goto error;
3365 }
3366 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003367 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003368 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003369
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003370 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003371 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003372
Radek Krejci363bd4a2016-07-29 14:30:20 +02003373 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
3374 /* leaf, leaf-list, list, container or anyxml */
3375 /* check possibility of statements combination */
3376 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003377 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003378 if (!rfn->target_type) {
3379 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3380 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
3381 goto error;
3382 }
3383 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003384 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003385 }
3386
3387 c_ftrs++;
3388 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003389 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003390 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003391 goto error;
3392 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003393
Michal Vasko345da0a2015-12-02 10:35:55 +01003394 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003395 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003396
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003397 /* process nodes with cardinality of 0..n */
3398 if (c_must) {
3399 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003400 if (!rfn->must) {
3401 LOGMEM;
3402 goto error;
3403 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003404 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02003405 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02003406 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003407 if (!rfn->iffeature) {
3408 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02003409 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003410 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003411 }
Radek Krejci200bf712016-08-16 17:11:04 +02003412 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003413 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Radek Krejci200bf712016-08-16 17:11:04 +02003414 if (!rfn->dflt) {
3415 LOGMEM;
3416 goto error;
3417 }
3418 }
Radek Krejcie534c132016-11-23 13:32:31 +01003419 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003420 /* some extensions may be already present from the substatements */
3421 reallocated = realloc(rfn->ext, (c_ext + rfn->ext_size) * sizeof *rfn->ext);
3422 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003423 LOGMEM;
3424 goto error;
3425 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01003426 rfn->ext = reallocated;
3427
3428 /* init memory */
3429 memset(&rfn->ext[rfn->ext_size], 0, c_ext * sizeof *rfn->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003430 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003431
Radek Krejcie534c132016-11-23 13:32:31 +01003432 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3433 if (strcmp(sub->ns->value, LY_NSYIN)) {
3434 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003435 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 +01003436 rfn->ext_size++;
3437 if (r) {
3438 goto error;
3439 }
3440 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003441 r = fill_yin_iffeature(uses, 0, sub, &rfn->iffeature[rfn->iffeature_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003442 rfn->iffeature_size++;
3443 if (r) {
3444 goto error;
3445 }
Radek Krejci200bf712016-08-16 17:11:04 +02003446 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01003447 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003448 rfn->must_size++;
3449 if (r) {
3450 goto error;
3451 }
Radek Krejci200bf712016-08-16 17:11:04 +02003452 } else { /* default */
3453 GETVAL(value, sub, "value");
3454
3455 /* check for duplicity */
3456 for (r = 0; r < rfn->dflt_size; r++) {
3457 if (ly_strequal(rfn->dflt[r], value, 1)) {
3458 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3459 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
3460 goto error;
3461 }
3462 }
3463 rfn->dflt[rfn->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02003464 }
3465 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003466
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003467 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003468
3469error:
3470
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003471 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003472}
3473
Michal Vasko0d343d12015-08-24 14:57:36 +02003474/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003475static int
Radek Krejcie534c132016-11-23 13:32:31 +01003476fill_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 +02003477{
Radek Krejcie534c132016-11-23 13:32:31 +01003478 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003479 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003480 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003481 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003482
Radek Krejcie534c132016-11-23 13:32:31 +01003483 /* init */
3484 memset(&exts, 0, sizeof exts);
3485
3486 LY_TREE_FOR_SAFE(yin->child, next, child) {
3487 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003488 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003489 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003490 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3491 /* extension */
3492 c_ext++;
3493 lyxml_unlink_elem(module->ctx, child, 2);
3494 lyxml_add_child(module->ctx, &exts, child);
3495 } else if (!strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003496 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01003497 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003498 goto error;
3499 }
3500 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01003501
Radek Krejci8d6b7422017-02-03 14:42:13 +01003502 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003503 goto error;
3504 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003505 } else if (!strcmp(child->name, "revision-date")) {
3506 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02003507 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3508 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003509 }
3510 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003511 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003512 goto error;
3513 }
3514 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003515
Radek Krejci8d6b7422017-02-03 14:42:13 +01003516 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003517 goto error;
3518 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003519 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003520 if (imp->dsc) {
3521 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3522 goto error;
3523 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003524 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003525 goto error;
3526 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003527 imp->dsc = read_yin_subnode(module->ctx, child, "text");
3528 if (!imp->dsc) {
3529 goto error;
3530 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003531 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003532 if (imp->ref) {
3533 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3534 goto error;
3535 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003536 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003537 goto error;
3538 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003539 imp->ref = read_yin_subnode(module->ctx, child, "text");
3540 if (!imp->ref) {
3541 goto error;
3542 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003543 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003544 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003545 goto error;
3546 }
3547 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003548
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003549 /* check mandatory information */
3550 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003551 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003552 goto error;
3553 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003554
Radek Krejcie534c132016-11-23 13:32:31 +01003555 /* process extensions */
3556 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003557 /* some extensions may be already present from the substatements */
3558 reallocated = realloc(imp->ext, (c_ext + imp->ext_size) * sizeof *imp->ext);
3559 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003560 LOGMEM;
3561 goto error;
3562 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003563 imp->ext = reallocated;
3564
3565 /* init memory */
3566 memset(&imp->ext[imp->ext_size], 0, c_ext * sizeof *imp->ext);
3567
Radek Krejcie534c132016-11-23 13:32:31 +01003568 LY_TREE_FOR_SAFE(exts.child, next, child) {
3569 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003570 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 +01003571 imp->ext_size++;
3572 if (r) {
3573 goto error;
3574 }
3575 }
3576 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003577
Radek Krejcie534c132016-11-23 13:32:31 +01003578 GETVAL(value, yin, "module");
Pavol Vicane994fda2016-03-22 10:47:58 +01003579 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02003580
3581error:
3582
Radek Krejcie534c132016-11-23 13:32:31 +01003583 while (exts.child) {
3584 lyxml_free(module->ctx, exts.child);
3585 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003586 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02003587}
3588
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003589/* logs directly
3590 * returns:
3591 * 0 - inc successfully filled
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003592 * -1 - error
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003593 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003594static int
Michal Vasko5ff78822016-02-12 09:33:31 +01003595fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
3596 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02003597{
Radek Krejcie534c132016-11-23 13:32:31 +01003598 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003599 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003600 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003601 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003602
Radek Krejcie534c132016-11-23 13:32:31 +01003603 /* init */
3604 memset(&exts, 0, sizeof exts);
3605
3606 LY_TREE_FOR_SAFE(yin->child, next, child) {
3607 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003608 /* garbage */
3609 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003610 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3611 /* extension */
3612 c_ext++;
3613 lyxml_unlink_elem(module->ctx, child, 2);
3614 lyxml_add_child(module->ctx, &exts, child);
3615 } else if (!strcmp(child->name, "revision-date")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003616 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003617 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003618 goto error;
3619 }
3620 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003621 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003622 goto error;
3623 }
3624 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003625
Radek Krejci8d6b7422017-02-03 14:42:13 +01003626 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003627 goto error;
3628 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003629 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003630 if (inc->dsc) {
3631 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3632 goto error;
3633 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003634 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003635 goto error;
3636 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003637 inc->dsc = read_yin_subnode(module->ctx, child, "text");
3638 if (!inc->dsc) {
3639 goto error;
3640 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003641 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003642 if (inc->ref) {
3643 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3644 goto error;
3645 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003646 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003647 goto error;
3648 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003649 inc->ref = read_yin_subnode(module->ctx, child, "text");
3650 if (!inc->ref) {
3651 goto error;
3652 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003653 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003654 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003655 goto error;
3656 }
3657 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003658
Radek Krejcie534c132016-11-23 13:32:31 +01003659 /* process extensions */
3660 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003661 /* some extensions may be already present from the substatements */
3662 reallocated = realloc(inc->ext, (c_ext + inc->ext_size) * sizeof *inc->ext);
3663 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003664 LOGMEM;
3665 goto error;
3666 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003667 inc->ext = reallocated;
3668
3669 /* init memory */
3670 memset(&inc->ext[inc->ext_size], 0, c_ext * sizeof *inc->ext);
3671
Radek Krejcie534c132016-11-23 13:32:31 +01003672 LY_TREE_FOR_SAFE(exts.child, next, child) {
3673 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003674 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 +01003675 inc->ext_size++;
3676 if (r) {
3677 goto error;
3678 }
3679 }
3680 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003681
Radek Krejcie534c132016-11-23 13:32:31 +01003682 GETVAL(value, yin, "module");
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003683 return lyp_check_include(submodule ? (struct lys_module *)submodule : module, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02003684
3685error:
3686
Radek Krejci83e3f5b2016-06-24 14:55:25 +02003687 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02003688}
3689
Michal Vasko0d343d12015-08-24 14:57:36 +02003690/* logs directly
3691 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003692 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02003693 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02003694 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003695 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003696static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01003697read_yin_common(struct lys_module *module, struct lys_node *parent, void *stmt, LYEXT_PAR stmt_type,
3698 struct lyxml_elem *xmlnode, int opt, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003699{
Radek Krejci07d0fb92017-01-13 14:11:05 +01003700 struct lys_node *node = stmt;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003701 const char *value;
3702 struct lyxml_elem *sub, *next;
3703 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003704
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003705 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003706 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003707 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003708
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003709 if (opt & OPT_IDENT) {
3710 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01003711 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003712 goto error;
3713 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003714 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003715 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003716
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003717 /* process local parameters */
3718 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003719 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003720 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003721 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02003722 continue;
3723 }
3724 if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejci6ff885d2017-01-03 14:06:22 +01003725 /* possibly an extension, keep the node for later processing, so skipping lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003726 continue;
3727 }
3728
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003729 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003730 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003731 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003732 goto error;
3733 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003734
Radek Krejci8d6b7422017-02-03 14:42:13 +01003735 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003736 goto error;
3737 }
3738
Radek Krejci1d82ef62015-08-07 14:44:40 +02003739 node->dsc = read_yin_subnode(ctx, sub, "text");
3740 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003741 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003742 }
3743 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003744 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003745 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003746 goto error;
3747 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003748
Radek Krejci8d6b7422017-02-03 14:42:13 +01003749 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003750 goto error;
3751 }
3752
Radek Krejci1d82ef62015-08-07 14:44:40 +02003753 node->ref = read_yin_subnode(ctx, sub, "text");
3754 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003755 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003756 }
3757 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003758 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003759 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003760 goto error;
3761 }
3762 GETVAL(value, sub, "value");
3763 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003764 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003765 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003766 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003767 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003768 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003769 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003770 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003771 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003772 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003773
Radek Krejci8d6b7422017-02-03 14:42:13 +01003774 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_STATUS, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003775 goto error;
3776 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003777 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3778 if (opt & OPT_CFG_PARSE) {
3779 if (node->flags & LYS_CONFIG_MASK) {
3780 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
3781 goto error;
3782 }
3783 GETVAL(value, sub, "value");
3784 if (!strcmp(value, "false")) {
3785 node->flags |= LYS_CONFIG_R;
3786 } else if (!strcmp(value, "true")) {
3787 node->flags |= LYS_CONFIG_W;
3788 } else {
3789 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3790 goto error;
3791 }
3792 node->flags |= LYS_CONFIG_SET;
Radek Krejci07d0fb92017-01-13 14:11:05 +01003793
Radek Krejci8d6b7422017-02-03 14:42:13 +01003794 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003795 goto error;
3796 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003797 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003798 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003799 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003800 continue;
3801 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003802 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003803 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003804
Michal Vaskoe022a562016-09-27 14:24:15 +02003805 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003806 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02003807 if (parent) {
3808 node->flags |= parent->flags & LYS_CONFIG_MASK;
3809 } else if (!parent) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003810 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003811 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003812 }
3813 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003814
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003815 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02003816
3817error:
3818
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003819 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003820}
3821
Michal Vasko0d343d12015-08-24 14:57:36 +02003822/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003823static struct lys_when *
Radek Krejci5323b492017-01-16 15:40:11 +01003824read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003825{
Radek Krejci76512572015-08-04 09:47:08 +02003826 struct lys_when *retval = NULL;
Radek Krejci5323b492017-01-16 15:40:11 +01003827 struct lyxml_elem *child, *next;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003828 const char *value;
3829
3830 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01003831 if (!retval) {
3832 LOGMEM;
3833 return NULL;
3834 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003835
3836 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01003837 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02003838 if (!retval->cond) {
3839 goto error;
3840 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003841
Radek Krejci5323b492017-01-16 15:40:11 +01003842 LY_TREE_FOR_SAFE(yin->child, next, child) {
3843 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003844 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003845 continue;
Radek Krejci5323b492017-01-16 15:40:11 +01003846 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3847 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01003848 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003849 goto error;
3850 }
3851 } else if (!strcmp(child->name, "description")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003852 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003853 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003854 goto error;
3855 }
Radek Krejci5323b492017-01-16 15:40:11 +01003856
Radek Krejci8d6b7422017-02-03 14:42:13 +01003857 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003858 goto error;
3859 }
3860
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003861 retval->dsc = read_yin_subnode(module->ctx, child, "text");
3862 if (!retval->dsc) {
3863 goto error;
3864 }
3865 } else if (!strcmp(child->name, "reference")) {
3866 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003867 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003868 goto error;
3869 }
Radek Krejci5323b492017-01-16 15:40:11 +01003870
Radek Krejci8d6b7422017-02-03 14:42:13 +01003871 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003872 goto error;
3873 }
3874
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003875 retval->ref = read_yin_subnode(module->ctx, child, "text");
3876 if (!retval->ref) {
3877 goto error;
3878 }
3879 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003880 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003881 goto error;
3882 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003883 }
3884
3885 return retval;
3886
3887error:
3888
Michal Vasko0308dd62015-10-07 09:14:40 +02003889 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003890 return NULL;
3891}
3892
Michal Vasko0d343d12015-08-24 14:57:36 +02003893/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003894static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003895read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02003896 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02003897{
Michal Vasko29fc0182015-08-24 15:02:39 +02003898 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003899 struct lys_node_case *cs;
3900 struct lys_node *retval, *node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01003901 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01003902 void *reallocated;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003903
Radek Krejcie867c852015-08-27 09:52:34 +02003904 /* init */
3905 memset(&root, 0, sizeof root);
3906
Radek Krejci1d82ef62015-08-07 14:44:40 +02003907 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01003908 if (!cs) {
3909 LOGMEM;
3910 return NULL;
3911 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003912 cs->nodetype = LYS_CASE;
3913 cs->prev = (struct lys_node *)cs;
3914 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003915
Radek Krejci07d0fb92017-01-13 14:11:05 +01003916 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
3917 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_INHERIT : 0), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003918 goto error;
3919 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003920
Radek Krejcia9544502015-08-14 08:24:29 +02003921 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3922
Michal Vasko3a0043f2015-08-12 12:11:30 +02003923 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003924 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003925 goto error;
3926 }
3927
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003928 /* process choice's specific children */
3929 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01003930 if (strcmp(sub->ns->value, LY_NSYIN)) {
3931 /* extension */
3932 c_ext++;
3933 } else if (!strcmp(sub->name, "container") ||
Michal Vasko29fc0182015-08-24 15:02:39 +02003934 !strcmp(sub->name, "leaf-list") ||
3935 !strcmp(sub->name, "leaf") ||
3936 !strcmp(sub->name, "list") ||
3937 !strcmp(sub->name, "uses") ||
3938 !strcmp(sub->name, "choice") ||
3939 !strcmp(sub->name, "anyxml")) {
3940
Michal Vaskof3930de2015-10-22 12:03:59 +02003941 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02003942 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003943 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02003944 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003945 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003946 if (cs->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003947 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003948 goto error;
3949 }
3950
Radek Krejci5323b492017-01-16 15:40:11 +01003951 cs->when = read_yin_when(module, sub, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02003952 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003953 goto error;
3954 }
Michal Vasko29fc0182015-08-24 15:02:39 +02003955
Michal Vasko345da0a2015-12-02 10:35:55 +01003956 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003957 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003958 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003959 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003960 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003961 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003962
Radek Krejci3cf9e222015-06-18 11:37:50 +02003963 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003964 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
3965 if (!cs->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003966 LOGMEM;
3967 goto error;
3968 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003969 }
Radek Krejcie534c132016-11-23 13:32:31 +01003970 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01003971 /* some extensions may be already present from the substatements */
3972 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
3973 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003974 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003975 goto error;
3976 }
Radek Krejci21c81652017-01-23 10:42:55 +01003977 retval->ext = reallocated;
3978
3979 /* init memory */
3980 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003981 }
Radek Krejci21c81652017-01-23 10:42:55 +01003982
Radek Krejcie534c132016-11-23 13:32:31 +01003983 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3984 if (strcmp(sub->ns->value, LY_NSYIN)) {
3985 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003986 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 +01003987 retval->ext_size++;
3988 if (ret) {
3989 goto error;
3990 }
3991 } else {
3992 /* if-feature */
3993 ret = fill_yin_iffeature(retval, 0, sub, &cs->iffeature[cs->iffeature_size], unres);
3994 cs->iffeature_size++;
3995 if (ret) {
3996 goto error;
3997 }
3998 }
3999 }
Radek Krejcib388c152015-06-04 17:03:03 +02004000
Michal Vasko29fc0182015-08-24 15:02:39 +02004001 /* last part - process data nodes */
4002 LY_TREE_FOR_SAFE(root.child, next, sub) {
4003 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004004 node = read_yin_container(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004005 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004006 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004007 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004008 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004009 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004010 node = read_yin_list(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004011 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004012 node = read_yin_choice(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004013 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004014 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004015 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004016 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004017 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004018 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004019 }
4020 if (!node) {
4021 goto error;
4022 }
4023
Michal Vasko345da0a2015-12-02 10:35:55 +01004024 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02004025 }
4026
Michal Vasko508a50d2016-09-07 14:50:33 +02004027 /* check XPath dependencies */
4028 if (cs->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4029 goto error;
4030 }
4031
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004032 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004033
4034error:
4035
Michal Vasko29fc0182015-08-24 15:02:39 +02004036 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004037 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02004038 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004039 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02004040
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004041 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004042}
4043
Michal Vasko0d343d12015-08-24 14:57:36 +02004044/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004045static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004046read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
4047 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004048{
Radek Krejci629cdef2016-06-06 15:06:36 +02004049 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004050 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004051 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02004052 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02004053 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01004054 int f_mand = 0, c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004055 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004056
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004057 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01004058 if (!choice) {
4059 LOGMEM;
4060 return NULL;
4061 }
Radek Krejci76512572015-08-04 09:47:08 +02004062 choice->nodetype = LYS_CHOICE;
4063 choice->prev = (struct lys_node *)choice;
4064 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004065
Radek Krejci07d0fb92017-01-13 14:11:05 +01004066 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4067 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004068 goto error;
4069 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004070
Radek Krejcia9544502015-08-14 08:24:29 +02004071 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4072
Michal Vasko3a0043f2015-08-12 12:11:30 +02004073 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004074 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004075 goto error;
4076 }
4077
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004078 /* process choice's specific children */
4079 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004080 if (strcmp(sub->ns->value, LY_NSYIN)) {
4081 /* extension */
4082 c_ext++;
4083 /* keep it for later processing, skip lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02004084 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004085 } else if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004086 if (!(node = read_yin_container(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004087 goto error;
4088 }
4089 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004090 if (!(node = read_yin_leaflist(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004091 goto error;
4092 }
4093 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004094 if (!(node = read_yin_leaf(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004095 goto error;
4096 }
4097 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004098 if (!(node = read_yin_list(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004099 goto error;
4100 }
4101 } else if (!strcmp(sub->name, "case")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004102 if (!(node = read_yin_case(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004103 goto error;
4104 }
4105 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004106 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004107 goto error;
4108 }
4109 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004110 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004111 goto error;
4112 }
4113 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02004114 if (dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004115 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004116 goto error;
4117 }
Radek Krejci21c81652017-01-23 10:42:55 +01004118
Radek Krejci8d6b7422017-02-03 14:42:13 +01004119 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004120 goto error;
4121 }
4122
Radek Krejci629cdef2016-06-06 15:06:36 +02004123 dflt = sub;
4124 lyxml_unlink_elem(ctx, dflt, 0);
Radek Krejcif9a312c2016-06-06 15:14:30 +02004125 continue;
4126 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
4127
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004128 } else if (!strcmp(sub->name, "mandatory")) {
4129 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004130 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004131 goto error;
4132 }
4133 /* just checking the flags in leaf is not sufficient, we would allow
4134 * multiple mandatory statements with the "false" value
4135 */
4136 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004137
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004138 GETVAL(value, sub, "value");
4139 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004140 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004141 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004142 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004143 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004144 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004145 goto error;
4146 } /* else false is the default value, so we can ignore it */
Radek Krejci21c81652017-01-23 10:42:55 +01004147
Radek Krejci8d6b7422017-02-03 14:42:13 +01004148 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004149 goto error;
4150 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004151 } else if (!strcmp(sub->name, "when")) {
4152 if (choice->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004153 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004154 goto error;
4155 }
4156
Radek Krejci5323b492017-01-16 15:40:11 +01004157 choice->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004158 if (!choice->when) {
4159 goto error;
4160 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004161 } else if (!strcmp(sub->name, "if-feature")) {
4162 c_ftrs++;
4163
Michal Vasko345da0a2015-12-02 10:35:55 +01004164 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02004165 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02004166 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004167 if (!(node = read_yin_choice(module, retval, sub, valid_config, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02004168 goto error;
4169 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004170 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004171 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004172 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004173 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004174
Radek Krejci1d82ef62015-08-07 14:44:40 +02004175 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01004176 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004177 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004178
Radek Krejci3cf9e222015-06-18 11:37:50 +02004179 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004180 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
4181 if (!choice->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004182 LOGMEM;
4183 goto error;
4184 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004185 }
Radek Krejcie534c132016-11-23 13:32:31 +01004186 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004187 /* some extensions may be already present from the substatements */
4188 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4189 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004190 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004191 goto error;
4192 }
Radek Krejci21c81652017-01-23 10:42:55 +01004193 retval->ext = reallocated;
4194
4195 /* init memory */
4196 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004197 }
4198
Radek Krejcie534c132016-11-23 13:32:31 +01004199 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4200 if (strcmp(sub->ns->value, LY_NSYIN)) {
4201 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004202 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 +01004203 retval->ext_size++;
4204 if (ret) {
4205 goto error;
4206 }
4207 } else {
4208 ret = fill_yin_iffeature(retval, 0, sub, &choice->iffeature[choice->iffeature_size], unres);
4209 choice->iffeature_size++;
4210 if (ret) {
4211 goto error;
4212 }
4213 }
4214 }
4215
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004216 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02004217 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004218 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "default", "choice");
Michal Vasko51e5c582017-01-19 14:16:39 +01004219 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004220 goto error;
4221 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004222
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004223 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02004224 if (dflt) {
4225 GETVAL(value, dflt, "value");
4226 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004227 goto error;
4228 }
Radek Krejci629cdef2016-06-06 15:06:36 +02004229 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004230 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004231
Michal Vasko508a50d2016-09-07 14:50:33 +02004232 /* check XPath dependencies */
4233 if (choice->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4234 goto error;
4235 }
4236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004237 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004238
4239error:
4240
Radek Krejci629cdef2016-06-06 15:06:36 +02004241 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004242 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004243
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004244 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004245}
4246
Michal Vasko0d343d12015-08-24 14:57:36 +02004247/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004248static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004249read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
4250 int valid_config, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02004251{
Radek Krejci76512572015-08-04 09:47:08 +02004252 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02004253 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004254 struct lyxml_elem *sub, *next;
4255 const char *value;
4256 int r;
4257 int f_mand = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004258 int c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004259 void *reallocated;
Radek Krejci863c2852015-06-03 15:47:11 +02004260
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004261 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01004262 if (!anyxml) {
4263 LOGMEM;
4264 return NULL;
4265 }
Radek Krejcibf2abff2016-08-23 15:51:52 +02004266 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02004267 anyxml->prev = (struct lys_node *)anyxml;
4268 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02004269
Radek Krejci07d0fb92017-01-13 14:11:05 +01004270 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4271 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004272 goto error;
4273 }
Radek Krejci863c2852015-06-03 15:47:11 +02004274
Radek Krejcia9544502015-08-14 08:24:29 +02004275 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004276
Radek Krejcic189a952016-07-11 15:27:07 +02004277 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004278 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004279 goto error;
4280 }
4281
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004282 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004283 if (strcmp(sub->ns->value, LY_NSYIN)) {
4284 /* extension */
4285 c_ext++;
4286 } else if (!strcmp(sub->name, "mandatory")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004287 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004288 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004289 goto error;
4290 }
4291 /* just checking the flags in leaf is not sufficient, we would allow
4292 * multiple mandatory statements with the "false" value
4293 */
4294 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02004295
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004296 GETVAL(value, sub, "value");
4297 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004298 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004299 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004300 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004301 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004302 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004303 goto error;
4304 }
4305 /* else false is the default value, so we can ignore it */
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004306
Radek Krejci8d6b7422017-02-03 14:42:13 +01004307 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004308 goto error;
4309 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004310 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004311 } else if (!strcmp(sub->name, "when")) {
4312 if (anyxml->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004313 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004314 goto error;
4315 }
4316
Radek Krejci5323b492017-01-16 15:40:11 +01004317 anyxml->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004318 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004319 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004320 goto error;
4321 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004322 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004323 } else if (!strcmp(sub->name, "must")) {
4324 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004325 } else if (!strcmp(sub->name, "if-feature")) {
4326 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02004327
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004328 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004329 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004330 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004331 }
4332 }
Radek Krejci863c2852015-06-03 15:47:11 +02004333
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004334 /* middle part - process nodes with cardinality of 0..n */
4335 if (c_must) {
4336 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004337 if (!anyxml->must) {
4338 LOGMEM;
4339 goto error;
4340 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004341 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004342 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004343 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
4344 if (!anyxml->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004345 LOGMEM;
4346 goto error;
4347 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004348 }
Radek Krejcie534c132016-11-23 13:32:31 +01004349 if (c_ext) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004350 /* some extensions may be already present from the substatements */
4351 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4352 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004353 LOGMEM;
4354 goto error;
4355 }
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004356 retval->ext = reallocated;
4357
4358 /* init memory */
4359 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004360 }
Radek Krejci863c2852015-06-03 15:47:11 +02004361
Radek Krejcie534c132016-11-23 13:32:31 +01004362 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4363 if (strcmp(sub->ns->value, LY_NSYIN)) {
4364 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004365 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 +01004366 retval->ext_size++;
4367 if (r) {
4368 goto error;
4369 }
4370 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004371 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004372 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004373 if (r) {
4374 goto error;
4375 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004376 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004377 r = fill_yin_iffeature(retval, 0, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004378 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004379 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004380 goto error;
4381 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004382 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004383 }
Radek Krejci863c2852015-06-03 15:47:11 +02004384
Michal Vasko508a50d2016-09-07 14:50:33 +02004385 /* check XPath dependencies */
4386 if ((anyxml->when || anyxml->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4387 goto error;
4388 }
4389
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004390 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02004391
4392error:
4393
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004394 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02004395
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004396 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02004397}
4398
Michal Vasko0d343d12015-08-24 14:57:36 +02004399/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004400static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004401read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004402 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004403{
Radek Krejci76512572015-08-04 09:47:08 +02004404 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004405 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004406 struct lyxml_elem *sub, *next;
4407 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01004408 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004409 int c_must = 0, c_ftrs = 0, f_mand = 0, c_ext = 0;
Radek Krejcifccd1442017-01-16 10:26:57 +01004410 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004411
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004412 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01004413 if (!leaf) {
4414 LOGMEM;
4415 return NULL;
4416 }
Radek Krejci76512572015-08-04 09:47:08 +02004417 leaf->nodetype = LYS_LEAF;
4418 leaf->prev = (struct lys_node *)leaf;
4419 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004420
Radek Krejci07d0fb92017-01-13 14:11:05 +01004421 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4422 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004423 goto error;
4424 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004425
Radek Krejcia9544502015-08-14 08:24:29 +02004426 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004427
Radek Krejcic189a952016-07-11 15:27:07 +02004428 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004429 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004430 goto error;
4431 }
4432
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004433 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004434 if (strcmp(sub->ns->value, LY_NSYIN)) {
4435 /* extension */
4436 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004437 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004438 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004439 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004440 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004441 goto error;
4442 }
Michal Vasko88c29542015-11-27 14:57:53 +01004443 /* HACK for unres */
4444 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004445 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004446 /* postpone type resolution when if-feature parsing is done since we need
4447 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004448 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004449 } else if (!strcmp(sub->name, "default")) {
4450 if (leaf->dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004451 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004452 goto error;
4453 }
4454 GETVAL(value, sub, "value");
4455 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci1abcdae2017-01-18 14:14:18 +01004456
Radek Krejci8d6b7422017-02-03 14:42:13 +01004457 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci1abcdae2017-01-18 14:14:18 +01004458 goto error;
4459 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004460 } else if (!strcmp(sub->name, "units")) {
4461 if (leaf->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004462 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004463 goto error;
4464 }
4465 GETVAL(value, sub, "name");
4466 leaf->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004467
Radek Krejci8d6b7422017-02-03 14:42:13 +01004468 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004469 goto error;
4470 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004471 } else if (!strcmp(sub->name, "mandatory")) {
4472 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004473 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004474 goto error;
4475 }
4476 /* just checking the flags in leaf is not sufficient, we would allow
4477 * multiple mandatory statements with the "false" value
4478 */
4479 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02004480
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004481 GETVAL(value, sub, "value");
4482 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004483 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004484 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004485 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004486 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004487 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004488 goto error;
4489 } /* else false is the default value, so we can ignore it */
Radek Krejcifccd1442017-01-16 10:26:57 +01004490
Radek Krejci8d6b7422017-02-03 14:42:13 +01004491 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004492 goto error;
4493 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004494 } else if (!strcmp(sub->name, "when")) {
4495 if (leaf->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004496 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004497 goto error;
4498 }
4499
Radek Krejci5323b492017-01-16 15:40:11 +01004500 leaf->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004501 if (!leaf->when) {
4502 goto error;
4503 }
4504
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004505 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02004506 c_must++;
4507 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004508 } else if (!strcmp(sub->name, "if-feature")) {
4509 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004510 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004511
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004512 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004513 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004514 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004515 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004516
Michal Vasko88c29542015-11-27 14:57:53 +01004517 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004518 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004519
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004520 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004521 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004522 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004523 goto error;
4524 }
Michal Vasko478c4652016-07-21 12:55:01 +02004525 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004526 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "mandatory", "leaf");
Michal Vasko51e5c582017-01-19 14:16:39 +01004527 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL,
Michal Vasko478c4652016-07-21 12:55:01 +02004528 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
4529 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004530 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004531
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004532 /* middle part - process nodes with cardinality of 0..n */
4533 if (c_must) {
4534 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004535 if (!leaf->must) {
4536 LOGMEM;
4537 goto error;
4538 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004539 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004540 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004541 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
4542 if (!leaf->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004543 LOGMEM;
4544 goto error;
4545 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004546 }
Radek Krejcie534c132016-11-23 13:32:31 +01004547 if (c_ext) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004548 /* some extensions may be already present from the substatements */
4549 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4550 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004551 LOGMEM;
4552 goto error;
4553 }
Radek Krejcifccd1442017-01-16 10:26:57 +01004554 retval->ext = reallocated;
4555
4556 /* init memory */
4557 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004558 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004559
Radek Krejcie534c132016-11-23 13:32:31 +01004560 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4561 if (strcmp(sub->ns->value, LY_NSYIN)) {
4562 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004563 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 +01004564 retval->ext_size++;
4565 if (r) {
4566 goto error;
4567 }
4568 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004569 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004570 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004571 if (r) {
4572 goto error;
4573 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004574 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004575 r = fill_yin_iffeature(retval, 0, sub, &leaf->iffeature[leaf->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004576 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004577 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004578 goto error;
4579 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004580 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004581 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004582
Radek Krejcicbb473e2016-09-16 14:48:32 +02004583 /* finalize type parsing */
4584 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
4585 leaf->type.der = NULL;
4586 goto error;
4587 }
4588
4589 /* check default value (if not defined, there still could be some restrictions
4590 * that need to be checked against a default value from a derived type) */
Radek Krejci51673202016-11-01 17:00:32 +01004591 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 +02004592 goto error;
4593 }
4594
Michal Vasko508a50d2016-09-07 14:50:33 +02004595 /* check XPath dependencies */
4596 if ((leaf->when || leaf->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4597 goto error;
4598 }
4599
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004600 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004601
4602error:
4603
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004604 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004605
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004606 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004607}
4608
Michal Vasko0d343d12015-08-24 14:57:36 +02004609/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004610static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004611read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004612 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004613{
Radek Krejci76512572015-08-04 09:47:08 +02004614 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004615 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004616 struct lyxml_elem *sub, *next;
4617 const char *value;
4618 char *endptr;
4619 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004620 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004621 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004622 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejci5323b492017-01-16 15:40:11 +01004623 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004624
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004625 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01004626 if (!llist) {
4627 LOGMEM;
4628 return NULL;
4629 }
Radek Krejci76512572015-08-04 09:47:08 +02004630 llist->nodetype = LYS_LEAFLIST;
4631 llist->prev = (struct lys_node *)llist;
4632 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004633
Radek Krejci07d0fb92017-01-13 14:11:05 +01004634 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4635 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004636 goto error;
4637 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004638
Radek Krejcia9544502015-08-14 08:24:29 +02004639 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004640
Radek Krejcic189a952016-07-11 15:27:07 +02004641 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004642 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004643 goto error;
4644 }
4645
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004646 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004647 if (strcmp(sub->ns->value, LY_NSYIN)) {
4648 /* extension */
4649 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004650 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004651 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004652 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004653 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004654 goto error;
4655 }
Michal Vasko88c29542015-11-27 14:57:53 +01004656 /* HACK for unres */
4657 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004658 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004659 /* postpone type resolution when if-feature parsing is done since we need
4660 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004661 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004662 } else if (!strcmp(sub->name, "units")) {
4663 if (llist->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004664 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004665 goto error;
4666 }
4667 GETVAL(value, sub, "name");
4668 llist->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004669
Radek Krejci8d6b7422017-02-03 14:42:13 +01004670 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004671 goto error;
4672 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004673 } else if (!strcmp(sub->name, "ordered-by")) {
4674 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004675 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004676 goto error;
4677 }
4678 /* just checking the flags in llist is not sufficient, we would
4679 * allow multiple ordered-by statements with the "system" value
4680 */
4681 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004682
Radek Krejci1574a8d2015-08-03 14:16:52 +02004683 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004684 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4685 * state data
4686 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004687 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004688 continue;
4689 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004690
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004691 GETVAL(value, sub, "value");
4692 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004693 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004694 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004695 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004696 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02004697 } /* else system is the default value, so we can ignore it */
4698
Radek Krejci8d6b7422017-02-03 14:42:13 +01004699 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004700 goto error;
4701 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004702 } else if (!strcmp(sub->name, "must")) {
4703 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02004704 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004705 } else if (!strcmp(sub->name, "if-feature")) {
4706 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004707 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02004708 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004709 /* read the default's extension instances */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004710 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 +01004711 goto error;
4712 }
4713
Radek Krejcid5a5c282016-08-15 15:38:08 +02004714 c_dflt++;
4715 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004716
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004717 } else if (!strcmp(sub->name, "min-elements")) {
4718 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004719 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004720 goto error;
4721 }
4722 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004723
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004724 GETVAL(value, sub, "value");
4725 while (isspace(value[0])) {
4726 value++;
4727 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004728
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004729 /* convert it to uint32_t */
4730 errno = 0;
4731 endptr = NULL;
4732 val = strtoul(value, &endptr, 10);
4733 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004734 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004735 goto error;
4736 }
4737 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004738 if (llist->max && (llist->min > llist->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004739 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004740 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004741 goto error;
4742 }
Radek Krejci5323b492017-01-16 15:40:11 +01004743
Radek Krejci8d6b7422017-02-03 14:42:13 +01004744 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004745 goto error;
4746 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004747 } else if (!strcmp(sub->name, "max-elements")) {
4748 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004749 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004750 goto error;
4751 }
4752 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004753
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004754 GETVAL(value, sub, "value");
4755 while (isspace(value[0])) {
4756 value++;
4757 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004758
Radek Krejci0d7b2472016-02-12 11:11:03 +01004759 if (!strcmp(value, "unbounded")) {
4760 llist->max = 0;
4761 } else {
4762 /* convert it to uint32_t */
4763 errno = 0;
4764 endptr = NULL;
4765 val = strtoul(value, &endptr, 10);
4766 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004767 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004768 goto error;
4769 }
4770 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004771 if (llist->min > llist->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004772 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004773 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004774 goto error;
4775 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004776 }
Radek Krejci5323b492017-01-16 15:40:11 +01004777
Radek Krejci8d6b7422017-02-03 14:42:13 +01004778 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004779 goto error;
4780 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004781 } else if (!strcmp(sub->name, "when")) {
4782 if (llist->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004783 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004784 goto error;
4785 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004786
Radek Krejci5323b492017-01-16 15:40:11 +01004787 llist->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004788 if (!llist->when) {
4789 goto error;
4790 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004791 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004792 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004793 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004794 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004795
Michal Vasko88c29542015-11-27 14:57:53 +01004796 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004797 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004798
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004799 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004800 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004801 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004802 goto error;
4803 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004804
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004805 /* middle part - process nodes with cardinality of 0..n */
4806 if (c_must) {
4807 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004808 if (!llist->must) {
4809 LOGMEM;
4810 goto error;
4811 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004812 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004813 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004814 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
4815 if (!llist->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004816 LOGMEM;
4817 goto error;
4818 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004819 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004820 if (c_dflt) {
4821 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
4822 if (!llist->dflt) {
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004823 LOGMEM;
4824 goto error;
4825 }
4826 }
Radek Krejcie534c132016-11-23 13:32:31 +01004827 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01004828 /* some extensions may be already present from the substatements */
4829 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4830 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004831 LOGMEM;
4832 goto error;
4833 }
Radek Krejci5323b492017-01-16 15:40:11 +01004834 retval->ext = reallocated;
4835
4836 /* init memory */
4837 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004838 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004839
Radek Krejcie534c132016-11-23 13:32:31 +01004840 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4841 if (strcmp(sub->ns->value, LY_NSYIN)) {
4842 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004843 r = lyp_yin_fill_ext(retval, LYEXT_PAR_NODE, 0, 0, module, sub, &retval->ext, retval->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01004844 retval->ext_size++;
4845 if (r) {
4846 goto error;
4847 }
4848 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004849 r = fill_yin_must(module, sub, &llist->must[llist->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004850 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004851 if (r) {
4852 goto error;
4853 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004854 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004855 r = fill_yin_iffeature(retval, 0, sub, &llist->iffeature[llist->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004856 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004857 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004858 goto error;
4859 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004860 } else if (!strcmp(sub->name, "default")) {
4861 GETVAL(value, sub, "value");
4862
Radek Krejciac1a52c2016-09-15 14:42:40 +02004863 /* check for duplicity in case of configuration data,
4864 * in case of status data duplicities are allowed */
4865 if (llist->flags & LYS_CONFIG_W) {
4866 for (r = 0; r < llist->dflt_size; r++) {
4867 if (ly_strequal(llist->dflt[r], value, 1)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004868 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, "default");
Michal Vasko51e5c582017-01-19 14:16:39 +01004869 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "Duplicated default value \"%s\".", value);
Radek Krejciac1a52c2016-09-15 14:42:40 +02004870 goto error;
4871 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004872 }
4873 }
4874 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004875 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004876 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004877
Radek Krejcicbb473e2016-09-16 14:48:32 +02004878 /* finalize type parsing */
4879 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
4880 llist->type.der = NULL;
4881 goto error;
4882 }
4883
Radek Krejcid5a5c282016-08-15 15:38:08 +02004884 if (llist->dflt_size && llist->min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004885 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "min-elements", "leaf-list");
Michal Vasko51e5c582017-01-19 14:16:39 +01004886 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02004887 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
4888 goto error;
4889 }
4890
4891 /* check default value (if not defined, there still could be some restrictions
4892 * that need to be checked against a default value from a derived type) */
4893 for (r = 0; r < llist->dflt_size; r++) {
Radek Krejci51673202016-11-01 17:00:32 +01004894 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
4895 (struct lys_node *)(&llist->dflt[r])) == -1) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02004896 goto error;
Radek Krejci25d782a2015-05-22 15:03:23 +02004897 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004898 }
4899
Michal Vasko508a50d2016-09-07 14:50:33 +02004900 /* check XPath dependencies */
4901 if ((llist->when || llist->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4902 goto error;
4903 }
4904
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004905 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004906
4907error:
4908
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004909 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004910
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004911 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004912}
4913
Michal Vasko0d343d12015-08-24 14:57:36 +02004914/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004915static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004916read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004917 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004918{
Radek Krejci1d82ef62015-08-07 14:44:40 +02004919 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02004920 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004921 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01004922 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01004923 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004924 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejci5c08a992016-11-02 13:30:04 +01004925 const char *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004926 char *auxs;
4927 unsigned long val;
Radek Krejcie36d7c72017-01-17 16:12:30 +01004928 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004929
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004930 /* init */
4931 memset(&root, 0, sizeof root);
4932 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02004933
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004934 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01004935 if (!list) {
4936 LOGMEM;
4937 return NULL;
4938 }
Radek Krejci76512572015-08-04 09:47:08 +02004939 list->nodetype = LYS_LIST;
4940 list->prev = (struct lys_node *)list;
4941 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004942
Radek Krejci07d0fb92017-01-13 14:11:05 +01004943 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4944 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004945 goto error;
4946 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004947
Radek Krejcia9544502015-08-14 08:24:29 +02004948 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4949
Radek Krejcic189a952016-07-11 15:27:07 +02004950 /* insert the node into the schema tree */
4951 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4952 goto error;
4953 }
4954
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004955 /* process list's specific children */
4956 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004957 if (strcmp(sub->ns->value, LY_NSYIN)) {
4958 /* extension */
4959 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004960 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02004961
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004962 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01004963 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004964 !strcmp(sub->name, "leaf-list") ||
4965 !strcmp(sub->name, "leaf") ||
4966 !strcmp(sub->name, "list") ||
4967 !strcmp(sub->name, "choice") ||
4968 !strcmp(sub->name, "uses") ||
4969 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004970 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02004971 !strcmp(sub->name, "action") ||
4972 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004973 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004974 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004975
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004976 /* array counters */
4977 } else if (!strcmp(sub->name, "key")) {
4978 /* check cardinality 0..1 */
4979 if (list->keys_size) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004980 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004981 goto error;
4982 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004983
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004984 /* count the number of keys */
4985 GETVAL(value, sub, "value");
Radek Krejci5c08a992016-11-02 13:30:04 +01004986 list->keys_str = lydict_insert(module->ctx, value, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004987 while ((value = strpbrk(value, " \t\n"))) {
4988 list->keys_size++;
4989 while (isspace(*value)) {
4990 value++;
4991 }
4992 }
4993 list->keys_size++;
4994 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01004995 if (!list->keys) {
4996 LOGMEM;
4997 goto error;
4998 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01004999
Radek Krejci8d6b7422017-02-03 14:42:13 +01005000 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_KEY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005001 goto error;
5002 }
5003 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005004 } else if (!strcmp(sub->name, "unique")) {
5005 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005006 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005007 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005008 } else if (!strcmp(sub->name, "typedef")) {
5009 c_tpdf++;
5010 } else if (!strcmp(sub->name, "must")) {
5011 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005012 } else if (!strcmp(sub->name, "if-feature")) {
5013 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02005014
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005015 /* optional stetments */
5016 } else if (!strcmp(sub->name, "ordered-by")) {
5017 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005018 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005019 goto error;
5020 }
5021 /* just checking the flags in llist is not sufficient, we would
5022 * allow multiple ordered-by statements with the "system" value
5023 */
5024 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005025
Radek Krejci1574a8d2015-08-03 14:16:52 +02005026 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005027 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
5028 * state data
5029 */
Michal Vasko345da0a2015-12-02 10:35:55 +01005030 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005031 continue;
5032 }
Radek Krejci345ad742015-06-03 11:04:18 +02005033
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005034 GETVAL(value, sub, "value");
5035 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02005036 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005037 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005038 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005039 goto error;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005040 } /* else system is the default value, so we can ignore it */
5041
Radek Krejci8d6b7422017-02-03 14:42:13 +01005042 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005043 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005044 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005045 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005046 } else if (!strcmp(sub->name, "min-elements")) {
5047 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005048 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005049 goto error;
5050 }
5051 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005052
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005053 GETVAL(value, sub, "value");
5054 while (isspace(value[0])) {
5055 value++;
5056 }
Radek Krejci345ad742015-06-03 11:04:18 +02005057
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005058 /* convert it to uint32_t */
5059 errno = 0;
5060 auxs = NULL;
5061 val = strtoul(value, &auxs, 10);
5062 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005063 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005064 goto error;
5065 }
5066 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005067 if (list->max && (list->min > list->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005068 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01005069 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005070 lyxml_free(module->ctx, sub);
5071 goto error;
5072 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005073 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005074 goto error;
5075 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005076 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005077 } else if (!strcmp(sub->name, "max-elements")) {
5078 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005079 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005080 goto error;
5081 }
5082 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005083
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005084 GETVAL(value, sub, "value");
5085 while (isspace(value[0])) {
5086 value++;
5087 }
Radek Krejci345ad742015-06-03 11:04:18 +02005088
Radek Krejci0d7b2472016-02-12 11:11:03 +01005089 if (!strcmp(value, "unbounded")) {
5090 list->max = 0;;
5091 } else {
5092 /* convert it to uint32_t */
5093 errno = 0;
5094 auxs = NULL;
5095 val = strtoul(value, &auxs, 10);
5096 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005097 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01005098 goto error;
5099 }
5100 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005101 if (list->min > list->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005102 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01005103 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005104 goto error;
5105 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005106 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005107 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005108 goto error;
5109 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005110 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005111 } else if (!strcmp(sub->name, "when")) {
5112 if (list->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005113 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005114 goto error;
5115 }
5116
Radek Krejci5323b492017-01-16 15:40:11 +01005117 list->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005118 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005119 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005120 goto error;
5121 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005122 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005123 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005124 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005125 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005126 }
5127 }
Radek Krejci345ad742015-06-03 11:04:18 +02005128
Michal Vaskoe022a562016-09-27 14:24:15 +02005129 /* check - if list is configuration, key statement is mandatory
5130 * (but only if we are not in a grouping or augment, then the check is deferred) */
5131 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT)); node = node->parent);
Radek Krejci5c08a992016-11-02 13:30:04 +01005132 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys_str) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005133 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005134 goto error;
5135 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005136
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005137 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5138 if (c_tpdf) {
5139 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005140 if (!list->tpdf) {
5141 LOGMEM;
5142 goto error;
5143 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005144 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005145 if (c_must) {
5146 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01005147 if (!list->must) {
5148 LOGMEM;
5149 goto error;
5150 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005151 }
5152 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005153 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
5154 if (!list->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005155 LOGMEM;
5156 goto error;
5157 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005158 }
Radek Krejcie534c132016-11-23 13:32:31 +01005159 if (c_ext) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005160 /* some extensions may be already present from the substatements */
5161 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5162 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005163 LOGMEM;
5164 goto error;
5165 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005166 retval->ext = reallocated;
5167
5168 /* init memory */
5169 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005170 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005171
Radek Krejcie534c132016-11-23 13:32:31 +01005172 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5173 if (strcmp(sub->ns->value, LY_NSYIN)) {
5174 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005175 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 +01005176 retval->ext_size++;
5177 if (r) {
5178 goto error;
5179 }
5180 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005181 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
5182 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005183 if (r) {
5184 goto error;
5185 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005186 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005187 r = fill_yin_iffeature(retval, 0, sub, &list->iffeature[list->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005188 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005189 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005190 goto error;
5191 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005192 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005193 r = fill_yin_must(module, sub, &list->must[list->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005194 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005195 if (r) {
5196 goto error;
5197 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005198 }
5199 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005200
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005201 /* last part - process data nodes */
5202 LY_TREE_FOR_SAFE(root.child, next, sub) {
5203 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005204 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005205 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005206 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005207 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005208 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005209 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005210 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005211 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005212 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005213 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005214 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005215 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005216 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005217 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005218 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005219 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005220 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005221 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005222 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005223 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005224 node = read_yin_notif(module, retval, sub, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005225 } else {
5226 LOGINT;
5227 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005228 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005229 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005230 goto error;
5231 }
Radek Krejci73adb602015-07-02 18:07:40 +02005232
Michal Vasko345da0a2015-12-02 10:35:55 +01005233 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005234 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005235
Radek Krejci5c08a992016-11-02 13:30:04 +01005236 if (list->keys_str) {
5237 /* check that we are not in grouping */
5238 for (node = parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
5239 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01005240 goto error;
5241 }
5242 } /* 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 +02005243
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005244 /* process unique statements */
5245 if (c_uniq) {
5246 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01005247 if (!list->unique) {
5248 LOGMEM;
5249 goto error;
5250 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005251
Radek Krejci461efb92016-02-12 15:52:18 +01005252 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
5253 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
5254 list->unique_size++;
5255 if (r) {
5256 goto error;
5257 }
5258
Radek Krejci8d6b7422017-02-03 14:42:13 +01005259 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub,
Radek Krejcie36d7c72017-01-17 16:12:30 +01005260 LYEXT_SUBSTMT_UNIQUE, list->unique_size - 1, unres)) {
5261 goto error;
5262 }
Radek Krejci461efb92016-02-12 15:52:18 +01005263 lyxml_free(module->ctx, sub);
5264 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005265 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005266
Michal Vasko508a50d2016-09-07 14:50:33 +02005267 /* check XPath dependencies */
5268 if ((list->when || list->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5269 goto error;
5270 }
5271
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005272 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005273
5274error:
5275
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005276 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005277 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005278 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005279 }
5280 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005281 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005282 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005283
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005284 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005285}
5286
Michal Vasko0d343d12015-08-24 14:57:36 +02005287/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005288static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005289read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02005290 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005291{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005292 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005293 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005294 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005295 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005296 const char *value;
Radek Krejci07d0fb92017-01-13 14:11:05 +01005297 void *reallocated;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005298 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005299 int c_tpdf = 0, c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005300
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005301 /* init */
5302 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005303
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005304 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01005305 if (!cont) {
5306 LOGMEM;
5307 return NULL;
5308 }
Radek Krejci76512572015-08-04 09:47:08 +02005309 cont->nodetype = LYS_CONTAINER;
5310 cont->prev = (struct lys_node *)cont;
5311 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005312
Radek Krejci07d0fb92017-01-13 14:11:05 +01005313 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
5314 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005315 goto error;
5316 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005317
Radek Krejcia9544502015-08-14 08:24:29 +02005318 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5319
Radek Krejcic189a952016-07-11 15:27:07 +02005320 /* insert the node into the schema tree */
5321 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5322 goto error;
5323 }
5324
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005325 /* process container's specific children */
5326 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005327 if (strcmp(sub->ns->value, LY_NSYIN)) {
5328 /* extension */
5329 c_ext++;
5330 } else if (!strcmp(sub->name, "presence")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005331 if (cont->presence) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005332 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005333 goto error;
5334 }
5335 GETVAL(value, sub, "value");
5336 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02005337
Radek Krejci8d6b7422017-02-03 14:42:13 +01005338 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005339 goto error;
5340 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005341 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005342 } else if (!strcmp(sub->name, "when")) {
5343 if (cont->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005344 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005345 goto error;
5346 }
5347
Radek Krejci5323b492017-01-16 15:40:11 +01005348 cont->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005349 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005350 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005351 goto error;
5352 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005353 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02005354
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005355 /* data statements */
5356 } else if (!strcmp(sub->name, "container") ||
5357 !strcmp(sub->name, "leaf-list") ||
5358 !strcmp(sub->name, "leaf") ||
5359 !strcmp(sub->name, "list") ||
5360 !strcmp(sub->name, "choice") ||
5361 !strcmp(sub->name, "uses") ||
5362 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005363 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005364 !strcmp(sub->name, "action") ||
5365 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005366 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005367 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005368
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005369 /* array counters */
5370 } else if (!strcmp(sub->name, "typedef")) {
5371 c_tpdf++;
5372 } else if (!strcmp(sub->name, "must")) {
5373 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005374 } else if (!strcmp(sub->name, "if-feature")) {
5375 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005376 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005377 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005378 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005379 }
5380 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005381
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005382 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5383 if (c_tpdf) {
5384 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005385 if (!cont->tpdf) {
5386 LOGMEM;
5387 goto error;
5388 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005389 }
5390 if (c_must) {
5391 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01005392 if (!cont->must) {
5393 LOGMEM;
5394 goto error;
5395 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005396 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005397 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005398 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
5399 if (!cont->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005400 LOGMEM;
5401 goto error;
5402 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005403 }
Radek Krejcie534c132016-11-23 13:32:31 +01005404 if (c_ext) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01005405 /* some extensions may be already present from the substatements */
5406 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5407 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005408 LOGMEM;
5409 goto error;
5410 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01005411 retval->ext = reallocated;
5412
5413 /* init memory */
5414 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005415 }
Radek Krejci800af702015-06-02 13:46:01 +02005416
Radek Krejcie534c132016-11-23 13:32:31 +01005417 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5418 if (strcmp(sub->ns->value, LY_NSYIN)) {
5419 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005420 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 +01005421 retval->ext_size++;
5422 if (r) {
5423 goto error;
5424 }
5425 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005426 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
5427 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005428 if (r) {
5429 goto error;
5430 }
5431 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005432 r = fill_yin_must(module, sub, &cont->must[cont->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005433 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005434 if (r) {
5435 goto error;
5436 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005437 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005438 r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005439 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005440 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005441 goto error;
5442 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005443 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005444 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005445
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005446 /* last part - process data nodes */
5447 LY_TREE_FOR_SAFE(root.child, next, sub) {
5448 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005449 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005450 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005451 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005452 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005453 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005454 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005455 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005456 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005457 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005458 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005459 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005460 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005461 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005462 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005463 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005464 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005465 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005466 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005467 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005468 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005469 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005470 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005471 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005472 goto error;
5473 }
Radek Krejci73adb602015-07-02 18:07:40 +02005474
Michal Vasko345da0a2015-12-02 10:35:55 +01005475 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005476 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005477
Michal Vasko508a50d2016-09-07 14:50:33 +02005478 /* check XPath dependencies */
5479 if ((cont->when || cont->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5480 goto error;
5481 }
5482
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005483 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005484
5485error:
5486
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005487 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005488 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005489 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005490 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005491
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005492 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005493}
5494
Michal Vasko0d343d12015-08-24 14:57:36 +02005495/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005496static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005497read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02005498 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005499{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005500 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005501 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005502 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005503 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005504 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005505 int c_tpdf = 0, c_ext = 0;
Radek Krejcifdc0d702017-01-23 15:58:38 +01005506 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005507
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005508 /* init */
5509 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005510
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005511 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01005512 if (!grp) {
5513 LOGMEM;
5514 return NULL;
5515 }
Radek Krejci76512572015-08-04 09:47:08 +02005516 grp->nodetype = LYS_GROUPING;
5517 grp->prev = (struct lys_node *)grp;
5518 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005519
Radek Krejci07d0fb92017-01-13 14:11:05 +01005520 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE , unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005521 goto error;
5522 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005523
Radek Krejcia9544502015-08-14 08:24:29 +02005524 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5525
Radek Krejcic189a952016-07-11 15:27:07 +02005526 /* insert the node into the schema tree */
5527 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5528 goto error;
5529 }
5530
Radek Krejci1d82ef62015-08-07 14:44:40 +02005531 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005532 if (strcmp(sub->ns->value, LY_NSYIN)) {
5533 /* extension */
5534 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005535
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005536 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005537 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005538 !strcmp(sub->name, "leaf-list") ||
5539 !strcmp(sub->name, "leaf") ||
5540 !strcmp(sub->name, "list") ||
5541 !strcmp(sub->name, "choice") ||
5542 !strcmp(sub->name, "uses") ||
5543 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005544 !strcmp(sub->name, "anyxml") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02005545 !strcmp(sub->name, "action") ||
5546 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005547 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005548 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005549
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005550 /* array counters */
5551 } else if (!strcmp(sub->name, "typedef")) {
5552 c_tpdf++;
5553 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005554 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005555 goto error;
5556 }
5557 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005558
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005559 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5560 if (c_tpdf) {
5561 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005562 if (!grp->tpdf) {
5563 LOGMEM;
5564 goto error;
5565 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005566 }
Radek Krejcie534c132016-11-23 13:32:31 +01005567 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01005568 /* some extensions may be already present from the substatements */
5569 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5570 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005571 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02005572 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005573 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01005574 retval->ext = reallocated;
5575
5576 /* init memory */
5577 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005578 }
Radek Krejcie534c132016-11-23 13:32:31 +01005579 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5580 if (strcmp(sub->ns->value, LY_NSYIN)) {
5581 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005582 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 +01005583 retval->ext_size++;
5584 if (r) {
5585 goto error;
5586 }
5587 } else {
5588 /* typedef */
5589 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
5590 grp->tpdf_size++;
5591 if (r) {
5592 goto error;
5593 }
5594 }
5595 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005596
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005597 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02005598 if (!root.child) {
5599 LOGWRN("Grouping \"%s\" without children.", retval->name);
5600 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005601 LY_TREE_FOR_SAFE(root.child, next, sub) {
5602 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005603 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005604 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005605 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005606 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005607 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005608 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005609 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005610 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005611 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005612 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005613 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005614 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005615 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005616 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005617 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005618 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005619 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005620 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005621 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02005622 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005623 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005624 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005625 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005626 goto error;
5627 }
Radek Krejci73adb602015-07-02 18:07:40 +02005628
Michal Vasko345da0a2015-12-02 10:35:55 +01005629 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005630 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005631
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005632 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005633
5634error:
5635
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005636 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005637 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005638 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005639 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005640
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005641 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005642}
5643
Michal Vasko0d343d12015-08-24 14:57:36 +02005644/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005645static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005646read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02005647 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005648{
Radek Krejcie0674f82015-06-15 13:58:51 +02005649 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005650 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02005651 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02005652 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005653 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005654 int c_tpdf = 0, c_must = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005655
Radek Krejcie0674f82015-06-15 13:58:51 +02005656 /* init */
5657 memset(&root, 0, sizeof root);
5658
Michal Vasko38d01f72015-06-15 09:41:06 +02005659 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01005660 if (!inout) {
5661 LOGMEM;
5662 return NULL;
5663 }
Radek Krejci6acc8012015-08-13 09:07:04 +02005664 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005665
5666 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02005667 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005668 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005669 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02005670 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005671 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005672 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02005673 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02005674 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02005675 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005676 }
5677
Radek Krejci76512572015-08-04 09:47:08 +02005678 retval = (struct lys_node *)inout;
Radek Krejcie7770892017-01-24 13:18:01 +01005679 retval->module = module;
Michal Vaskoebeac942015-06-15 12:11:50 +02005680
Radek Krejcia9544502015-08-14 08:24:29 +02005681 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5682
Radek Krejcic189a952016-07-11 15:27:07 +02005683 /* insert the node into the schema tree */
5684 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5685 goto error;
5686 }
5687
Michal Vasko38d01f72015-06-15 09:41:06 +02005688 /* data statements */
5689 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie7770892017-01-24 13:18:01 +01005690 if (!sub->ns) {
5691 /* garbage */
5692 lyxml_free(module->ctx, sub);
5693 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01005694 /* extension */
5695 c_ext++;
5696 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005697 !strcmp(sub->name, "leaf-list") ||
5698 !strcmp(sub->name, "leaf") ||
5699 !strcmp(sub->name, "list") ||
5700 !strcmp(sub->name, "choice") ||
5701 !strcmp(sub->name, "uses") ||
5702 !strcmp(sub->name, "grouping") ||
5703 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005704 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005705 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005706
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005707 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005708 } else if (!strcmp(sub->name, "typedef")) {
5709 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02005710
Radek Krejci1a31efe2016-07-29 11:04:16 +02005711 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005712 c_must++;
5713
Michal Vasko38d01f72015-06-15 09:41:06 +02005714 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005715 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005716 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005717 }
5718 }
5719
5720 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5721 if (c_tpdf) {
5722 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005723 if (!inout->tpdf) {
5724 LOGMEM;
5725 goto error;
5726 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005727 }
Radek Krejci19332802016-07-29 10:39:46 +02005728 if (c_must) {
5729 inout->must = calloc(c_must, sizeof *inout->must);
5730 if (!inout->must) {
5731 LOGMEM;
5732 goto error;
5733 }
5734 }
Radek Krejcie534c132016-11-23 13:32:31 +01005735 if (c_ext) {
5736 inout->ext = calloc(c_ext, sizeof *inout->ext);
5737 if (!inout->ext) {
5738 LOGMEM;
5739 goto error;
5740 }
5741 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005742
Radek Krejcie534c132016-11-23 13:32:31 +01005743 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5744 if (strcmp(sub->ns->value, LY_NSYIN)) {
5745 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005746 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 +01005747 retval->ext_size++;
5748 if (r) {
5749 goto error;
5750 }
5751 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005752 r = fill_yin_must(module, sub, &inout->must[inout->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02005753 inout->must_size++;
5754 if (r) {
5755 goto error;
5756 }
5757 } else { /* typedef */
5758 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
5759 inout->tpdf_size++;
5760 if (r) {
5761 goto error;
5762 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005763 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005764 }
5765
5766 /* last part - process data nodes */
5767 LY_TREE_FOR_SAFE(root.child, next, sub) {
5768 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005769 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005770 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005771 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005772 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005773 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005774 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005775 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005776 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005777 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005778 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005779 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005780 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005781 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005782 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005783 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005784 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005785 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005786 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005787 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005788 goto error;
5789 }
Radek Krejci73adb602015-07-02 18:07:40 +02005790
Michal Vasko345da0a2015-12-02 10:35:55 +01005791 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005792 }
5793
Michal Vasko508a50d2016-09-07 14:50:33 +02005794 /* check XPath dependencies */
5795 if (inout->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5796 goto error;
5797 }
5798
Michal Vasko38d01f72015-06-15 09:41:06 +02005799 return retval;
5800
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005801error:
Michal Vasko38d01f72015-06-15 09:41:06 +02005802
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005803 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02005804 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005805 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005806 }
5807
5808 return NULL;
5809}
5810
Michal Vasko0d343d12015-08-24 14:57:36 +02005811/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005812static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005813read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02005814 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02005815{
Michal Vaskoc6551b32015-06-16 10:51:43 +02005816 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005817 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005818 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005819 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005820 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005821 int c_tpdf = 0, c_ftrs = 0, c_must = 0, c_ext = 0;
Radek Krejci478ef1d2017-01-24 13:56:09 +01005822 void *reallocated;
Michal Vasko0ea41032015-06-16 08:53:55 +02005823
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005824 if (parent && (module->version < 2)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005825 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "notification");
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005826 return NULL;
5827 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005828
Michal Vaskoc6551b32015-06-16 10:51:43 +02005829 memset(&root, 0, sizeof root);
5830
Michal Vasko0ea41032015-06-16 08:53:55 +02005831 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01005832 if (!notif) {
5833 LOGMEM;
5834 return NULL;
5835 }
Radek Krejci76512572015-08-04 09:47:08 +02005836 notif->nodetype = LYS_NOTIF;
5837 notif->prev = (struct lys_node *)notif;
5838 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005839
Radek Krejci07d0fb92017-01-13 14:11:05 +01005840 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005841 goto error;
5842 }
5843
Radek Krejcia9544502015-08-14 08:24:29 +02005844 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5845
Radek Krejcic189a952016-07-11 15:27:07 +02005846 /* insert the node into the schema tree */
5847 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5848 goto error;
5849 }
5850
Michal Vasko0ea41032015-06-16 08:53:55 +02005851 /* process rpc's specific children */
5852 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005853 if (strcmp(sub->ns->value, LY_NSYIN)) {
5854 /* extension */
5855 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005856 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02005857
Michal Vasko0ea41032015-06-16 08:53:55 +02005858 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005859 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005860 !strcmp(sub->name, "leaf-list") ||
5861 !strcmp(sub->name, "leaf") ||
5862 !strcmp(sub->name, "list") ||
5863 !strcmp(sub->name, "choice") ||
5864 !strcmp(sub->name, "uses") ||
5865 !strcmp(sub->name, "grouping") ||
5866 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005867 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005868 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02005869
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005870 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02005871 } else if (!strcmp(sub->name, "typedef")) {
5872 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005873 } else if (!strcmp(sub->name, "if-feature")) {
5874 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02005875 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005876 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02005877 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005878 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02005879 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02005880 }
5881 }
5882
5883 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5884 if (c_tpdf) {
5885 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005886 if (!notif->tpdf) {
5887 LOGMEM;
5888 goto error;
5889 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005890 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005891 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005892 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
5893 if (!notif->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005894 LOGMEM;
5895 goto error;
5896 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005897 }
Radek Krejci19332802016-07-29 10:39:46 +02005898 if (c_must) {
5899 notif->must = calloc(c_must, sizeof *notif->must);
5900 if (!notif->must) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005901 LOGMEM;
5902 goto error;
5903 }
5904 }
Radek Krejcie534c132016-11-23 13:32:31 +01005905 if (c_ext) {
Radek Krejci478ef1d2017-01-24 13:56:09 +01005906 /* some extensions may be already present from the substatements */
5907 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5908 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005909 LOGMEM;
5910 goto error;
5911 }
Radek Krejci478ef1d2017-01-24 13:56:09 +01005912 retval->ext = reallocated;
5913
5914 /* init memory */
5915 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005916 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005917
Radek Krejcie534c132016-11-23 13:32:31 +01005918 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5919 if (strcmp(sub->ns->value, LY_NSYIN)) {
5920 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005921 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 +01005922 retval->ext_size++;
5923 if (r) {
5924 goto error;
5925 }
5926 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005927 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
5928 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02005929 if (r) {
5930 goto error;
5931 }
Radek Krejci96299152016-06-22 10:17:50 +02005932 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005933 r = fill_yin_iffeature(retval, 0, sub, &notif->iffeature[notif->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005934 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005935 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005936 goto error;
5937 }
Radek Krejci19332802016-07-29 10:39:46 +02005938 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005939 r = fill_yin_must(module, sub, &notif->must[notif->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02005940 notif->must_size++;
Radek Krejci0b24d752015-07-02 15:02:27 +02005941 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005942 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005943 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005944 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005945 }
5946
5947 /* last part - process data nodes */
5948 LY_TREE_FOR_SAFE(root.child, next, sub) {
5949 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005950 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005951 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005952 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005953 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005954 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005955 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005956 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005957 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005958 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005959 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005960 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005961 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005962 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005963 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005964 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005965 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005966 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005967 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005968 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005969 goto error;
5970 }
Radek Krejci73adb602015-07-02 18:07:40 +02005971
Michal Vasko345da0a2015-12-02 10:35:55 +01005972 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02005973 }
5974
Michal Vasko508a50d2016-09-07 14:50:33 +02005975 /* check XPath dependencies */
5976 if (notif->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5977 goto error;
5978 }
5979
Michal Vasko0ea41032015-06-16 08:53:55 +02005980 return retval;
5981
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005982error:
Michal Vasko0ea41032015-06-16 08:53:55 +02005983
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005984 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02005985 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005986 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02005987 }
5988
5989 return NULL;
5990}
5991
Michal Vasko0d343d12015-08-24 14:57:36 +02005992/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005993static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005994read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005995 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005996{
Radek Krejcie0674f82015-06-15 13:58:51 +02005997 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005998 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005999 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02006000 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006001 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01006002 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0, c_ext = 0;
Radek Krejci94596cf2017-01-24 13:19:16 +01006003 void *reallocated;
Michal Vasko38d01f72015-06-15 09:41:06 +02006004
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006005 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006006 if (module->version < 2) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006007 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "action");
Michal Vaskobb174852016-07-25 11:00:21 +02006008 return NULL;
6009 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006010 for (node = parent; node; node = lys_parent(node)) {
Radek Krejcia3b19f72016-09-30 13:02:45 +02006011 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006012 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006013 LOGVAL(LYE_INPAR, LY_VLOG_LYS, parent, strnodetype(node->nodetype), "action");
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006014 return NULL;
6015 }
6016 }
6017 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006018
Radek Krejcie0674f82015-06-15 13:58:51 +02006019 /* init */
6020 memset(&root, 0, sizeof root);
6021
Michal Vasko38d01f72015-06-15 09:41:06 +02006022 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01006023 if (!rpc) {
6024 LOGMEM;
6025 return NULL;
6026 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006027 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02006028 rpc->prev = (struct lys_node *)rpc;
6029 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006030
Radek Krejci07d0fb92017-01-13 14:11:05 +01006031 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006032 goto error;
6033 }
6034
Radek Krejcia9544502015-08-14 08:24:29 +02006035 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
6036
Radek Krejcic189a952016-07-11 15:27:07 +02006037 /* insert the node into the schema tree */
6038 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6039 goto error;
6040 }
6041
Michal Vasko38d01f72015-06-15 09:41:06 +02006042 /* process rpc's specific children */
6043 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006044 if (strcmp(sub->ns->value, LY_NSYIN)) {
6045 /* extension */
6046 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006047 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006048 } else if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006049 if (c_input) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006050 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006051 goto error;
6052 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006053 c_input++;
Michal Vaskof3930de2015-10-22 12:03:59 +02006054 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006055 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006056 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006057 if (c_output) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006058 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006059 goto error;
6060 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006061 c_output++;
Michal Vaskof3930de2015-10-22 12:03:59 +02006062 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006063 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006064
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006065 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02006066 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02006067 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006068 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006069
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006070 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02006071 } else if (!strcmp(sub->name, "typedef")) {
6072 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006073 } else if (!strcmp(sub->name, "if-feature")) {
6074 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006075 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006076 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006077 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02006078 }
6079 }
6080
6081 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6082 if (c_tpdf) {
6083 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01006084 if (!rpc->tpdf) {
6085 LOGMEM;
6086 goto error;
6087 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006088 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006089 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006090 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
6091 if (!rpc->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01006092 LOGMEM;
6093 goto error;
6094 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006095 }
Radek Krejcie534c132016-11-23 13:32:31 +01006096 if (c_ext) {
Radek Krejci94596cf2017-01-24 13:19:16 +01006097 /* some extensions may be already present from the substatements */
6098 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
6099 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01006100 LOGMEM;
6101 goto error;
6102 }
Radek Krejci94596cf2017-01-24 13:19:16 +01006103 retval->ext = reallocated;
6104
6105 /* init memory */
6106 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006107 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006108
Radek Krejcie534c132016-11-23 13:32:31 +01006109 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6110 if (strcmp(sub->ns->value, LY_NSYIN)) {
6111 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006112 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 +01006113 retval->ext_size++;
6114 if (r) {
6115 goto error;
6116 }
6117 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006118 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
6119 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006120 if (r) {
6121 goto error;
6122 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006123 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006124 r = fill_yin_iffeature(retval, 0, sub, &rpc->iffeature[rpc->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006125 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006126 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006127 goto error;
6128 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006129 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006130 }
6131
6132 /* last part - process data nodes */
6133 LY_TREE_FOR_SAFE(root.child, next, sub) {
6134 if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006135 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006136 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006137 node = read_yin_input_output(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006138 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006139 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006140 goto error;
6141 }
Radek Krejci73adb602015-07-02 18:07:40 +02006142
Michal Vasko345da0a2015-12-02 10:35:55 +01006143 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006144 }
6145
Michal Vasko38d01f72015-06-15 09:41:06 +02006146 return retval;
6147
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006148error:
Michal Vasko38d01f72015-06-15 09:41:06 +02006149
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006150 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006151 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006152 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006153 }
6154
6155 return NULL;
6156}
6157
Michal Vasko0d343d12015-08-24 14:57:36 +02006158/* logs directly
6159 *
Radek Krejci74705112015-06-05 10:25:44 +02006160 * resolve - referenced grouping should be bounded to the namespace (resolved)
6161 * only when uses does not appear in grouping. In a case of grouping's uses,
6162 * we just get information but we do not apply augment or refine to it.
6163 */
Radek Krejci76512572015-08-04 09:47:08 +02006164static struct lys_node *
Radek Krejci3440cc52016-06-23 17:03:59 +02006165read_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 +02006166{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006167 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02006168 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006169 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006170 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01006171 int c_ref = 0, c_aug = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006172 int r;
Radek Krejcifdc0d702017-01-23 15:58:38 +01006173 void *reallocated;
Radek Krejci74705112015-06-05 10:25:44 +02006174
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006175 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01006176 if (!uses) {
6177 LOGMEM;
6178 return NULL;
6179 }
Radek Krejci76512572015-08-04 09:47:08 +02006180 uses->nodetype = LYS_USES;
6181 uses->prev = (struct lys_node *)uses;
6182 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02006183
Radek Krejcia9544502015-08-14 08:24:29 +02006184 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006185 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02006186
Radek Krejci07d0fb92017-01-13 14:11:05 +01006187 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006188 goto error;
6189 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006190
Radek Krejcia9544502015-08-14 08:24:29 +02006191 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
6192
Radek Krejcic189a952016-07-11 15:27:07 +02006193 /* insert the node into the schema tree */
6194 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6195 goto error;
6196 }
6197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006198 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02006199 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006200 if (strcmp(sub->ns->value, LY_NSYIN)) {
6201 /* extension */
6202 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006203 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006204 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006205 c_ref++;
6206 } else if (!strcmp(sub->name, "augment")) {
6207 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006208 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02006209 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006210 } else if (!strcmp(sub->name, "when")) {
6211 if (uses->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006212 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006213 goto error;
6214 }
6215
Radek Krejci5323b492017-01-16 15:40:11 +01006216 uses->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006217 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006218 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006219 goto error;
6220 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006221 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006222 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006223 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006224 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006225 }
6226 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006227
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006228 /* process properties with cardinality 0..n */
6229 if (c_ref) {
6230 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01006231 if (!uses->refine) {
6232 LOGMEM;
6233 goto error;
6234 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006235 }
6236 if (c_aug) {
6237 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01006238 if (!uses->augment) {
6239 LOGMEM;
6240 goto error;
6241 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006242 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006243 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006244 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
6245 if (!uses->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01006246 LOGMEM;
6247 goto error;
6248 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006249 }
Radek Krejcie534c132016-11-23 13:32:31 +01006250 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01006251 /* some extensions may be already present from the substatements */
6252 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
6253 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01006254 LOGMEM;
6255 goto error;
6256 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01006257 retval->ext = reallocated;
6258
6259 /* init memory */
6260 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006261 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006262
Radek Krejcie534c132016-11-23 13:32:31 +01006263 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6264 if (strcmp(sub->ns->value, LY_NSYIN)) {
6265 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006266 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 +01006267 retval->ext_size++;
6268 if (r) {
6269 goto error;
6270 }
6271 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02006272 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006273 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006274 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006275 goto error;
6276 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006277 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006278 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
6279 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006280 if (r) {
6281 goto error;
6282 }
6283 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006284 r = fill_yin_iffeature(retval, 0, sub, &uses->iffeature[uses->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006285 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006286 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006287 goto error;
6288 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006289 }
6290 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006291
Radek Krejci48464ed2016-03-17 15:44:09 +01006292 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006293 goto error;
6294 }
Radek Krejci74705112015-06-05 10:25:44 +02006295
Michal Vasko508a50d2016-09-07 14:50:33 +02006296 /* check XPath dependencies */
6297 if (uses->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
6298 goto error;
6299 }
6300
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006301 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006302
6303error:
6304
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006305 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006306
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006307 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006308}
6309
Michal Vasko0d343d12015-08-24 14:57:36 +02006310/* logs directly
6311 *
6312 * common code for yin_read_module() and yin_read_submodule()
6313 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006314static int
Radek Krejcic071c542016-01-27 14:57:51 +01006315read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
6316 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02006317{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006318 struct ly_ctx *ctx = module->ctx;
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006319 struct lyxml_elem *next, *child, *child2, root, grps, augs, revs, exts;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006320 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006321 struct lys_module *trg;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006322 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01006323 int i, r, ret = -1;
Radek Krejcic071c542016-01-27 14:57:51 +01006324 int version_flag = 0;
Michal Vasko5de8a022017-02-08 10:57:26 +01006325 /* (sub)module substatements are ordered in groups, increment this value when moving to another group
6326 * 0 - header-stmts, 1 - linkage-stmts, 2 - meta-stmts, 3 - revision-stmts, 4 - body-stmts */
6327 int substmt_group;
6328 /* just remember last substatement for logging */
6329 const char *substmt_prev;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006330 /* counters */
Radek Krejcie534c132016-11-23 13:32:31 +01006331 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;
6332 int c_ext = 0, c_extinst = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01006333 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006334
Radek Krejcic071c542016-01-27 14:57:51 +01006335 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02006336 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01006337
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006338 /* init */
6339 memset(&root, 0, sizeof root);
6340 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006341 memset(&augs, 0, sizeof augs);
Radek Krejcie534c132016-11-23 13:32:31 +01006342 memset(&exts, 0, sizeof exts);
PavolVican9e81c6a2017-02-09 13:09:07 +01006343 memset(&revs, 0, sizeof revs);
Radek Krejcie0674f82015-06-15 13:58:51 +02006344
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006345 /*
6346 * in the first run, we process elements with cardinality of 1 or 0..1 and
6347 * count elements with cardinality 0..n. Data elements (choices, containers,
6348 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
6349 * need have all top-level and groupings already prepared at that time. In
6350 * the middle loop, we process other elements with carinality of 0..n since
6351 * we need to allocate arrays to store them.
6352 */
Michal Vasko5de8a022017-02-08 10:57:26 +01006353 substmt_group = 0;
6354 substmt_prev = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006355 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01006356 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02006357 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01006358 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006359 continue;
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006360 } else if (strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01006361 /* possible extension instance */
6362 lyxml_unlink_elem(module->ctx, child, 2);
6363 lyxml_add_child(module->ctx, &exts, child);
6364 c_extinst++;
6365 } else if (!submodule && !strcmp(child->name, "namespace")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006366 if (substmt_group > 0) {
6367 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6368 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6369 child->name, substmt_prev);
6370 goto error;
6371 }
6372
PavolVican9e81c6a2017-02-09 13:09:07 +01006373 if (trg->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006374 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006375 goto error;
6376 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006377 GETVAL(value, child, "uri");
PavolVican9e81c6a2017-02-09 13:09:07 +01006378 trg->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006379
Radek Krejci8d6b7422017-02-03 14:42:13 +01006380 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_NAMESPACE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006381 goto error;
6382 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006383 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006384
6385 substmt_prev = "namespace";
Radek Krejcic071c542016-01-27 14:57:51 +01006386 } else if (!submodule && !strcmp(child->name, "prefix")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006387 if (substmt_group > 0) {
6388 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6389 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6390 child->name, substmt_prev);
6391 goto error;
6392 }
6393
PavolVican9e81c6a2017-02-09 13:09:07 +01006394 if (trg->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006395 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006396 goto error;
6397 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006398 GETVAL(value, child, "value");
PavolVican9e81c6a2017-02-09 13:09:07 +01006399 if (lyp_check_identifier(value, LY_IDENT_PREFIX, trg, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006400 goto error;
6401 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006402 trg->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006403
Radek Krejci8d6b7422017-02-03 14:42:13 +01006404 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006405 goto error;
6406 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006407 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006408
6409 substmt_prev = "prefix";
Radek Krejcic071c542016-01-27 14:57:51 +01006410 } else if (submodule && !strcmp(child->name, "belongs-to")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006411 if (substmt_group > 0) {
6412 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6413 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6414 child->name, substmt_prev);
6415 goto error;
6416 }
6417
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006418 if (trg->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006419 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006420 goto error;
6421 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006422 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01006423 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006424 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006425 goto error;
6426 }
Radek Krejcif3886932015-06-04 17:36:06 +02006427
Radek Krejci8d6b7422017-02-03 14:42:13 +01006428 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_BELONGSTO, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006429 goto error;
6430 }
6431
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006432 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006433 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006434 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006435 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006436 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006437 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006438 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006439 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006440 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006441 goto error;
6442 }
6443 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006444 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006445 /* check here differs from a generic prefix check, since this prefix
6446 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02006447 */
Radek Krejci48464ed2016-03-17 15:44:09 +01006448 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006449 goto error;
6450 }
Radek Krejcic071c542016-01-27 14:57:51 +01006451 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02006452
Radek Krejci8d6b7422017-02-03 14:42:13 +01006453 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 +01006454 goto error;
6455 }
6456
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006457 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01006458 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02006459
Michal Vasko5de8a022017-02-08 10:57:26 +01006460 substmt_prev = "belongs-to";
6461
Radek Krejcieb00f512015-07-01 16:44:58 +02006462 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006463 } else if (!strcmp(child->name, "import")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006464 if (substmt_group > 1) {
6465 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6466 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6467 child->name, substmt_prev);
6468 goto error;
6469 }
6470 substmt_group = 1;
6471
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006472 c_imp++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006473
6474 substmt_prev = "import";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006475 } else if (!strcmp(child->name, "revision")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006476 if (substmt_group > 3) {
6477 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6478 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6479 child->name, substmt_prev);
6480 goto error;
6481 }
6482 substmt_group = 3;
6483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006484 c_rev++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006485
PavolVican9e81c6a2017-02-09 13:09:07 +01006486 lyxml_unlink_elem(ctx, child, 2);
6487 lyxml_add_child(ctx, &revs, child);
6488
Michal Vasko5de8a022017-02-08 10:57:26 +01006489 substmt_prev = "revision";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006490 } else if (!strcmp(child->name, "typedef")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006491 substmt_group = 4;
6492
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006493 c_tpdf++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006494
6495 substmt_prev = "typedef";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006496 } else if (!strcmp(child->name, "identity")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006497 substmt_group = 4;
6498
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006499 c_ident++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006500
6501 substmt_prev = "identity";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006502 } else if (!strcmp(child->name, "include")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006503 if (substmt_group > 1) {
6504 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6505 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6506 child->name, substmt_prev);
6507 goto error;
6508 }
6509 substmt_group = 1;
6510
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006511 c_inc++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006512
6513 substmt_prev = "include";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006514 } else if (!strcmp(child->name, "augment")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006515 substmt_group = 4;
6516
Radek Krejcif5be10f2015-06-16 13:29:36 +02006517 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006518 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01006519 lyxml_unlink_elem(ctx, child, 2);
6520 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006521
Michal Vasko5de8a022017-02-08 10:57:26 +01006522 substmt_prev = "augment";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006523 } else if (!strcmp(child->name, "feature")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006524 substmt_group = 4;
6525
Radek Krejci3cf9e222015-06-18 11:37:50 +02006526 c_ftrs++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006527
Michal Vasko5de8a022017-02-08 10:57:26 +01006528 substmt_prev = "feature";
Michal Vasko5de8a022017-02-08 10:57:26 +01006529
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006530 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006531 } else if (!strcmp(child->name, "container") ||
6532 !strcmp(child->name, "leaf-list") ||
6533 !strcmp(child->name, "leaf") ||
6534 !strcmp(child->name, "list") ||
6535 !strcmp(child->name, "choice") ||
6536 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006537 !strcmp(child->name, "anyxml") ||
6538 !strcmp(child->name, "rpc") ||
6539 !strcmp(child->name, "notification")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006540 substmt_group = 4;
6541
Radek Krejcic071c542016-01-27 14:57:51 +01006542 lyxml_unlink_elem(ctx, child, 2);
6543 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006544
Michal Vasko5de8a022017-02-08 10:57:26 +01006545 substmt_prev = "data definition";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006546 } else if (!strcmp(child->name, "grouping")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006547 substmt_group = 4;
6548
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006549 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01006550 lyxml_unlink_elem(ctx, child, 2);
6551 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006552
Michal Vasko5de8a022017-02-08 10:57:26 +01006553 substmt_prev = "grouping";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006554 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006555 } else if (!strcmp(child->name, "description")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006556 if (substmt_group > 2) {
6557 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6558 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6559 child->name, substmt_prev);
6560 goto error;
6561 }
6562 substmt_group = 2;
6563
Radek Krejcic071c542016-01-27 14:57:51 +01006564 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006565 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006566 goto error;
6567 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006568 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006569 goto error;
6570 }
Radek Krejcic071c542016-01-27 14:57:51 +01006571 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006572 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006573 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006574 goto error;
6575 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006576
6577 substmt_prev = "description";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006578 } else if (!strcmp(child->name, "reference")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006579 if (substmt_group > 2) {
6580 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6581 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6582 child->name, substmt_prev);
6583 goto error;
6584 }
6585 substmt_group = 2;
6586
Radek Krejcic071c542016-01-27 14:57:51 +01006587 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006588 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006589 goto error;
6590 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006591 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006592 goto error;
6593 }
Radek Krejcic071c542016-01-27 14:57:51 +01006594 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006595 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006596 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006597 goto error;
6598 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006599
6600 substmt_prev = "reference";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006601 } else if (!strcmp(child->name, "organization")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006602 if (substmt_group > 2) {
6603 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6604 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6605 child->name, substmt_prev);
6606 goto error;
6607 }
6608 substmt_group = 2;
6609
Radek Krejcic071c542016-01-27 14:57:51 +01006610 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006611 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006612 goto error;
6613 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006614 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_ORGANIZATION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006615 goto error;
6616 }
Radek Krejcic071c542016-01-27 14:57:51 +01006617 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006618 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006619 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006620 goto error;
6621 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006622
6623 substmt_prev = "organization";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006624 } else if (!strcmp(child->name, "contact")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006625 if (substmt_group > 2) {
6626 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6627 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6628 child->name, substmt_prev);
6629 goto error;
6630 }
6631 substmt_group = 2;
6632
Radek Krejcic071c542016-01-27 14:57:51 +01006633 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006634 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006635 goto error;
6636 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006637 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_CONTACT, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006638 goto error;
6639 }
Radek Krejcic071c542016-01-27 14:57:51 +01006640 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006641 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006642 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006643 goto error;
6644 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006645
6646 substmt_prev = "contact";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006647 } else if (!strcmp(child->name, "yang-version")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006648 if (substmt_group > 0) {
6649 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6650 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6651 child->name, substmt_prev);
6652 goto error;
6653 }
6654
Radek Krejcic071c542016-01-27 14:57:51 +01006655 if (version_flag) {
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 Krejci1d82ef62015-08-07 14:44:40 +02006659 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02006660 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006661 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006662 goto error;
6663 }
Radek Krejcic071c542016-01-27 14:57:51 +01006664 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006665 if (!strcmp(value, "1")) {
6666 if (submodule) {
6667 if (module->version > 1) {
6668 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6669 goto error;
6670 }
6671 } else {
6672 module->version = 1;
6673 }
6674 } else {
6675 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006676 if (module->version < 2) {
Michal Vasko88de3e42016-06-29 11:05:32 +02006677 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6678 goto error;
6679 }
6680 } else {
6681 module->version = 2;
6682 }
6683 }
6684
Radek Krejci8d6b7422017-02-03 14:42:13 +01006685 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_VERSION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006686 goto error;
6687 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006688 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006689
Michal Vasko5de8a022017-02-08 10:57:26 +01006690 substmt_prev = "yang-version";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006691 } else if (!strcmp(child->name, "extension")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006692 substmt_group = 4;
6693
Radek Krejcia1a6b762016-11-14 09:53:38 +09006694 c_ext++;
Radek Krejci5166a892015-07-02 16:44:24 +02006695
Michal Vasko5de8a022017-02-08 10:57:26 +01006696 substmt_prev = "extension";
Radek Krejcia1a6b762016-11-14 09:53:38 +09006697 } else if (!strcmp(child->name, "deviation")) {
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006698 substmt_group = 4;
6699
Radek Krejcia1a6b762016-11-14 09:53:38 +09006700 c_dev++;
6701
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006702 substmt_prev = "deviation";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006703 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01006704 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006705 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006706 }
6707 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006708
Radek Krejcic071c542016-01-27 14:57:51 +01006709 /* check for mandatory statements */
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006710 if (submodule) {
6711 if (!submodule->prefix) {
6712 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
6713 goto error;
6714 }
6715 if (!version_flag) {
6716 /* check version compatibility with the main module */
6717 if (module->version > 1) {
6718 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6719 goto error;
6720 }
6721 }
6722 } else {
PavolVican9e81c6a2017-02-09 13:09:07 +01006723 if (!trg->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006724 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006725 goto error;
6726 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006727 if (!trg->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006728 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006729 goto error;
6730 }
6731 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02006732
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006733 /* allocate arrays for elements with cardinality of 0..n */
6734 if (c_imp) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006735 trg->imp = calloc(c_imp, sizeof *trg->imp);
Radek Krejcic071c542016-01-27 14:57:51 +01006736 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01006737 LOGMEM;
6738 goto error;
6739 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006740 }
6741 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006742 trg->rev = calloc(c_rev, sizeof *trg->rev);
6743 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01006744 LOGMEM;
6745 goto error;
6746 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006747 }
6748 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01006749 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
6750 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01006751 LOGMEM;
6752 goto error;
6753 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006754 }
6755 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01006756 trg->ident = calloc(c_ident, sizeof *trg->ident);
6757 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01006758 LOGMEM;
6759 goto error;
6760 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006761 }
6762 if (c_inc) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006763 trg->inc = calloc(c_inc, sizeof *trg->inc);
Radek Krejcic071c542016-01-27 14:57:51 +01006764 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01006765 LOGMEM;
6766 goto error;
6767 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006768 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006769 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01006770 trg->augment = calloc(c_aug, sizeof *trg->augment);
6771 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01006772 LOGMEM;
6773 goto error;
6774 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006775 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006776 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01006777 trg->features = calloc(c_ftrs, sizeof *trg->features);
6778 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01006779 LOGMEM;
6780 goto error;
6781 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006782 }
Radek Krejcieb00f512015-07-01 16:44:58 +02006783 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006784 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
6785 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01006786 LOGMEM;
6787 goto error;
6788 }
Radek Krejcieb00f512015-07-01 16:44:58 +02006789 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09006790 if (c_ext) {
6791 trg->extensions = calloc(c_ext, sizeof *trg->extensions);
6792 if (!trg->extensions) {
6793 LOGMEM;
6794 goto error;
6795 }
6796 }
Radek Krejcie534c132016-11-23 13:32:31 +01006797 if (c_extinst) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006798 /* some extensions may be already present from the substatements */
6799 reallocated = realloc(trg->ext, (c_extinst + trg->ext_size) * sizeof *trg->ext);
6800 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01006801 LOGMEM;
6802 goto error;
6803 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006804 trg->ext = reallocated;
6805
6806 /* init memory */
6807 memset(&trg->ext[trg->ext_size], 0, c_extinst * sizeof *trg->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006808 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006809
PavolVican9e81c6a2017-02-09 13:09:07 +01006810 /* middle part 1 - process revision and then check whether this (sub)module was not already parsed, add it there */
6811 LY_TREE_FOR_SAFE(revs.child, next, child) {
6812 GETVAL(value, child, "date");
6813 if (lyp_check_date(value)) {
6814 goto error;
6815 }
6816 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
6817 /* check uniqueness of the revision date - not required by RFC */
6818 for (i = 0; i < trg->rev_size; i++) {
6819 if (!strcmp(value, trg->rev[i].date)) {
6820 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
6821 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
6822 }
6823 }
6824
6825 LY_TREE_FOR(child->child, child2) {
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006826 if (!child2->ns) {
6827 /* garbage */
6828 continue;
6829 } else if (strcmp(child2->ns->value, LY_NSYIN)) {
6830 /* possible extension instance */
6831 if (lyp_yin_parse_subnode_ext(trg, &trg->rev[trg->rev_size], LYEXT_PAR_REVISION,
6832 child2, LYEXT_SUBSTMT_SELF, 0, unres)) {
6833 goto error;
6834 }
6835 } else if (!strcmp(child2->name, "description")) {
PavolVican9e81c6a2017-02-09 13:09:07 +01006836 if (trg->rev[trg->rev_size].dsc) {
6837 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
6838 goto error;
6839 }
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006840 if (lyp_yin_parse_subnode_ext(trg, &trg->rev[trg->rev_size], LYEXT_PAR_REVISION,
6841 child2, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
6842 goto error;
6843 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006844 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
6845 if (!trg->rev[trg->rev_size].dsc) {
6846 goto error;
6847 }
6848 } else if (!strcmp(child2->name, "reference")) {
6849 if (trg->rev[trg->rev_size].ref) {
6850 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
6851 goto error;
6852 }
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006853 if (lyp_yin_parse_subnode_ext(trg, &trg->rev[trg->rev_size], LYEXT_PAR_REVISION,
6854 child2, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
6855 goto error;
6856 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006857 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
6858 if (!trg->rev[trg->rev_size].ref) {
6859 goto error;
6860 }
6861 } else {
6862 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
6863 goto error;
6864 }
6865 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006866 trg->rev_size++;
6867
6868 lyxml_free(ctx, child);
6869 }
6870
6871 /* check the module with respect to the context now */
6872 if (!submodule) {
6873 switch (lyp_ctx_check_module(module)) {
6874 case -1:
6875 goto error;
6876 case 0:
6877 break;
6878 case 1:
6879 /* it's already there */
6880 ret = 1;
6881 goto error;
6882 }
6883 }
6884
6885 /* middle part 2 - process nodes with cardinality of 0..n except the data nodes and augments */
Michal Vasko2f7925f2015-10-21 15:06:56 +02006886 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02006887 if (!strcmp(child->name, "import")) {
Radek Krejcie534c132016-11-23 13:32:31 +01006888 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size], unres);
Radek Krejcic071c542016-01-27 14:57:51 +01006889 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006890 if (r) {
6891 goto error;
6892 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006893
Radek Krejci1d82ef62015-08-07 14:44:40 +02006894 } else if (!strcmp(child->name, "include")) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006895 r = fill_yin_include(module, submodule, child, &trg->inc[trg->inc_size], unres);
6896 trg->inc_size++;
6897 if (r) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006898 goto error;
6899 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006900
Radek Krejci1d82ef62015-08-07 14:44:40 +02006901 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006902 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
6903 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006904 if (r) {
6905 goto error;
6906 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006907
Radek Krejci1d82ef62015-08-07 14:44:40 +02006908 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006909 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
6910 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006911 if (r) {
6912 goto error;
6913 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006914
Radek Krejci1d82ef62015-08-07 14:44:40 +02006915 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006916 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
6917 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006918 if (r) {
6919 goto error;
6920 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006921
Radek Krejcia1a6b762016-11-14 09:53:38 +09006922 } else if (!strcmp(child->name, "extension")) {
Radek Krejcie534c132016-11-23 13:32:31 +01006923 r = fill_yin_extension(trg, child, &trg->extensions[trg->extensions_size], unres);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006924 trg->extensions_size++;
6925 if (r) {
6926 goto error;
6927 }
6928
Radek Krejci1d82ef62015-08-07 14:44:40 +02006929 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006930 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
6931 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02006932 if (r) {
6933 goto error;
6934 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006935 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006936 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006937
Radek Krejcie534c132016-11-23 13:32:31 +01006938 /* process extension instances */
6939 LY_TREE_FOR_SAFE(exts.child, next, child) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006940 r = lyp_yin_fill_ext(trg, LYEXT_PAR_MODULE, 0, 0, trg, child, &trg->ext, trg->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01006941 trg->ext_size++;
6942 if (r) {
6943 goto error;
6944 }
6945 }
6946
Radek Krejcif5be10f2015-06-16 13:29:36 +02006947 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01006948 * refer to them. Submodule's data nodes are stored in the
6949 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006950 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006951 LY_TREE_FOR_SAFE(grps.child, next, child) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006952 node = read_yin_grouping(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006953 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006954 goto error;
6955 }
Radek Krejci74705112015-06-05 10:25:44 +02006956
Michal Vasko345da0a2015-12-02 10:35:55 +01006957 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006958 }
Radek Krejci74705112015-06-05 10:25:44 +02006959
Radek Krejcif5be10f2015-06-16 13:29:36 +02006960 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006961 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02006962
Radek Krejci1d82ef62015-08-07 14:44:40 +02006963 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006964 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006965 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006966 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006967 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006968 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006969 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006970 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006971 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006972 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006973 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02006974 node = read_yin_uses(trg, NULL, child, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006975 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02006976 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 1, unres);
6977 } else if (!strcmp(child->name, "anydata")) {
6978 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006979 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006980 node = read_yin_rpc_action(trg, NULL, child, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006981 } else if (!strcmp(child->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006982 node = read_yin_notif(trg, NULL, child, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006983 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006984 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006985 goto error;
6986 }
Radek Krejci25d782a2015-05-22 15:03:23 +02006987
Michal Vasko345da0a2015-12-02 10:35:55 +01006988 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006989 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006990
Michal Vasko2f7925f2015-10-21 15:06:56 +02006991 /* ... and finally augments (last, so we can augment our data, for instance) */
6992 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01006993 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
6994 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02006995
Michal Vasko2f7925f2015-10-21 15:06:56 +02006996 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02006997 goto error;
6998 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006999 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02007000 }
7001
PavolVican9e81c6a2017-02-09 13:09:07 +01007002 return 0;
Radek Krejciefaeba32015-05-27 14:30:57 +02007003
7004error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007005 while (root.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007006 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007007 }
7008 while (grps.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007009 lyxml_free(ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007010 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02007011 while (augs.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01007012 lyxml_free(ctx, augs.child);
7013 }
7014 while (revs.child) {
7015 lyxml_free(ctx, revs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02007016 }
Radek Krejcie534c132016-11-23 13:32:31 +01007017 while (exts.child) {
7018 lyxml_free(module->ctx, exts.child);
7019 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007020
PavolVican9e81c6a2017-02-09 13:09:07 +01007021 return ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007022}
7023
Michal Vasko0d343d12015-08-24 14:57:36 +02007024/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007025struct lys_submodule *
7026yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02007027{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007028 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01007029 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007030 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02007031
Michal Vasko5a721fd2016-02-16 12:16:48 +01007032 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02007033
Radek Krejci722b0072016-02-01 17:09:45 +01007034 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007035 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01007036 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007037 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007038
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007039 /* check root element */
7040 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01007041 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007042 goto error;
7043 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007044
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007045 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01007046 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007047 goto error;
7048 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007049
Michal Vasko5a721fd2016-02-16 12:16:48 +01007050 submodule = calloc(1, sizeof *submodule);
7051 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007052 LOGMEM;
7053 goto error;
7054 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007055
Michal Vasko5a721fd2016-02-16 12:16:48 +01007056 submodule->ctx = module->ctx;
7057 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
7058 submodule->type = 1;
7059 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02007060
Michal Vasko5a721fd2016-02-16 12:16:48 +01007061 LOGVRB("Reading submodule \"%s\".", submodule->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007062 /* module cannot be changed in this case and 1 cannot be returned */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007063 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007064 goto error;
7065 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007066
Radek Krejci33fc4772017-01-26 16:00:35 +01007067 lyp_sort_revisions((struct lys_module *)submodule);
7068
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007069 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01007070 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02007071
Michal Vasko5a721fd2016-02-16 12:16:48 +01007072 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007073 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02007074
7075error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007076 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01007077 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01007078 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01007079
Michal Vasko5a721fd2016-02-16 12:16:48 +01007080 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01007081 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01007082 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01007083 }
7084
Michal Vasko5a721fd2016-02-16 12:16:48 +01007085 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01007086
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007087 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
7088 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007089 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01007090 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02007091}
7092
Michal Vasko0d343d12015-08-24 14:57:36 +02007093/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02007094struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01007095yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02007096{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007097 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01007098 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01007099 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007100 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01007101 int ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007102
Radek Krejcic071c542016-01-27 14:57:51 +01007103 unres = calloc(1, sizeof *unres);
7104 if (!unres) {
7105 LOGMEM;
7106 return NULL;
7107 }
7108
Radek Krejci722b0072016-02-01 17:09:45 +01007109 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007110 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01007111 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007112 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007113
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007114 /* check root element */
7115 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci9a909bd2016-10-24 15:45:51 +02007116 if (ly_strequal("submodule", yin->name, 0)) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007117 LOGVAL(LYE_SUBMODULE, LY_VLOG_NONE, NULL);
7118 } else {
7119 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci9a909bd2016-10-24 15:45:51 +02007120 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007121 goto error;
7122 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007123
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007124 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01007125 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007126 goto error;
7127 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007128
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007129 module = calloc(1, sizeof *module);
7130 if (!module) {
7131 LOGMEM;
7132 goto error;
7133 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007134
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007135 module->ctx = ctx;
7136 module->name = lydict_insert(ctx, value, strlen(value));
7137 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02007138 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02007139
Michal Vasko9f258e42016-02-11 11:36:27 +01007140 LOGVRB("Reading module \"%s\".", module->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007141 ret = read_sub_module(module, NULL, yin, unres);
7142 if (ret == -1) {
Radek Krejcic071c542016-01-27 14:57:51 +01007143 goto error;
7144 }
7145
PavolVican9e81c6a2017-02-09 13:09:07 +01007146 if (ret == 1) {
7147 assert(!unres->count);
7148 } else {
7149 /* resolve rest of unres items */
7150 if (unres->count && resolve_unres_schema(module, unres)) {
7151 goto error;
7152 }
7153
7154 /* check correctness of includes */
7155 if (lyp_check_include_missing(module)) {
7156 goto error;
7157 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007158 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007159
Radek Krejci95f22ae2017-01-20 14:25:53 +01007160 lyp_sort_revisions(module);
Radek Krejci6bd2c022017-02-01 15:04:49 +01007161
7162 if (lyp_rfn_apply_ext(module) || lyp_deviation_apply_ext(module)) {
7163 goto error;
7164 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01007165
Radek Krejciff4874d2016-03-07 12:30:50 +01007166 if (revision) {
7167 /* check revision of the parsed model */
7168 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01007169 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
7170 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01007171 goto error;
7172 }
7173 }
7174
PavolVican9e81c6a2017-02-09 13:09:07 +01007175 /* add into context if not already there */
7176 if (!ret) {
7177 if (module->deviation_size && !module->implemented) {
7178 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
7179 /* deviations always causes target to be made implemented,
7180 * but augents and leafrefs not, so we have to apply them now */
7181 if (lys_set_implemented(module)) {
7182 goto error;
7183 }
7184 }
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007185
PavolVican9e81c6a2017-02-09 13:09:07 +01007186 if (lyp_ctx_add_module(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02007187 goto error;
7188 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007189 } else {
7190 /* free what was parsed */
7191 lys_free(module, NULL, 0);
7192
7193 /* get the model from the context */
7194 module = (struct lys_module *)ly_ctx_get_module(ctx, value, revision);
7195 assert(module);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007196 }
7197
Michal Vasko345da0a2015-12-02 10:35:55 +01007198 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01007199 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01007200 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007201 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007202
7203error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007204 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01007205 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01007206 unres_schema_free(module, &unres);
7207
7208 if (!module) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007209 if (ly_vecode != LYVE_SUBMODULE) {
7210 LOGERR(ly_errno, "Module parsing failed.");
7211 }
Radek Krejcib8c07b82016-02-12 11:11:55 +01007212 return NULL;
7213 }
7214
7215 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02007216
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007217 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01007218 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007219 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007220}
Radek Krejci8d6b7422017-02-03 14:42:13 +01007221
Radek Krejcic1885952017-02-07 09:37:51 +01007222static int
7223yin_parse_extcomplex_bool(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007224 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007225 const char *true_val, const char *false_val, struct unres_schema *unres)
7226{
7227 uint8_t *val;
7228 const char *str;
7229 struct lyext_substmt *info;
7230
7231 val = lys_ext_complex_get_substmt(stmt, ext, &info);
7232 if (!val) {
7233 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7234 return EXIT_FAILURE;
7235 }
7236 if (*val) {
7237 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7238 return EXIT_FAILURE;
7239 }
7240
Radek Krejcibe336392017-02-07 10:54:24 +01007241 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007242 return EXIT_FAILURE;
7243 }
7244
7245 str = lyxml_get_attr(node, "value", NULL);
7246 if (!str) {
7247 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
7248 } else if (true_val && !strcmp(true_val, str)) {
7249 /* true value */
7250 *val = 1;
7251 } else if (false_val && !strcmp(false_val, str)) {
7252 /* false value */
7253 *val = 2;
7254 } else {
7255 /* unknown value */
7256 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
7257 return EXIT_FAILURE;
7258 }
7259
7260 return EXIT_SUCCESS;
7261}
7262
Radek Krejci8d6b7422017-02-03 14:42:13 +01007263/*
7264 * argelem - 1 if the value is stored in a standalone YIN element, 0 if stored as attribute
7265 * argname - name of the element/attribute where the value is stored
7266 */
7267static int
7268yin_parse_extcomplex_str(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007269 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejci8d6b7422017-02-03 14:42:13 +01007270 int argelem, const char *argname, struct unres_schema *unres)
7271{
7272 int c;
7273 const char **str, ***p = NULL;
7274 void *reallocated;
7275 struct lyext_substmt *info;
7276
7277 str = lys_ext_complex_get_substmt(stmt, ext, &info);
7278 if (!str) {
7279 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7280 return EXIT_FAILURE;
7281 }
7282 if (info->cardinality < LY_STMT_CARD_SOME && *str) {
7283 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7284 return EXIT_FAILURE;
7285 }
7286
7287 c = 0;
7288 if (info->cardinality >= LY_STMT_CARD_SOME) {
7289 /* there can be multiple instances, str is actually const char *** */
7290 p = (const char ***)str;
Radek Krejci56c80412017-02-09 10:44:16 +01007291 if (!p[0]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007292 /* allocate initial array */
Radek Krejci56c80412017-02-09 10:44:16 +01007293 p[0] = malloc(2 * sizeof(const char *));
7294 if (stmt == LY_STMT_BELONGSTO) {
7295 /* allocate another array for the belongs-to's prefixes */
7296 p[1] = malloc(2 * sizeof(const char *));
7297 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007298 } else {
Radek Krejci56c80412017-02-09 10:44:16 +01007299 /* get the index in the array to add new item */
7300 for (c = 0; p[0][c]; c++);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007301 }
Radek Krejci56c80412017-02-09 10:44:16 +01007302 str = p[0];
Radek Krejci8d6b7422017-02-03 14:42:13 +01007303 }
Radek Krejcibe336392017-02-07 10:54:24 +01007304 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, stmt, c, unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007305 return EXIT_FAILURE;
7306 }
7307
7308 if (argelem) {
Radek Krejci56c80412017-02-09 10:44:16 +01007309 str[c] = read_yin_subnode(mod->ctx, node, argname);
7310 if (!str[c]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007311 return EXIT_FAILURE;
7312 }
Radek Krejci56c80412017-02-09 10:44:16 +01007313 } else {
7314 str[c] = lyxml_get_attr(node, argname, NULL);
7315 if (!str[c]) {
7316 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, argname, node->name);
7317 return EXIT_FAILURE;
7318 } else {
7319 str[c] = lydict_insert(mod->ctx, str[c], 0);
7320 }
7321
7322 if (stmt == LY_STMT_BELONGSTO) {
7323 /* get the belongs-to's mandatory prefix substatement */
7324 if (!node->child) {
7325 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", node->name);
7326 return EXIT_FAILURE;
7327 } else if (strcmp(node->child->name, "prefix")) {
7328 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
7329 return EXIT_FAILURE;
7330 } else if (node->child->next) {
7331 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
7332 return EXIT_FAILURE;
7333 }
7334 /* and now finally get the value */
7335 if (p) {
7336 str = p[1];
7337 } else {
7338 str++;
7339 }
7340 str[c] = lyxml_get_attr(node->child, "value", ((void *)0));
7341 if (!str[c]) {
7342 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
7343 return EXIT_FAILURE;
7344 }
7345 str[c] = lydict_insert(mod->ctx, str[c], 0);
7346
7347 if (!str[c] || lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node->child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
7348 return EXIT_FAILURE;
7349 }
7350 }
7351 }
7352 if (p) {
7353 /* enlarge the array(s) */
7354 reallocated = realloc(p[0], (c + 2) * sizeof(const char *));
7355 if (!reallocated) {
7356 LOGMEM;
7357 lydict_remove(mod->ctx, p[0][c]);
7358 p[0][c] = NULL;
7359 return EXIT_FAILURE;
7360 }
7361 p[0] = reallocated;
7362 p[0][c + 1] = NULL;
7363
7364 if (stmt == LY_STMT_BELONGSTO) {
7365 /* enlarge the second belongs-to's array with prefixes */
7366 reallocated = realloc(p[1], (c + 2) * sizeof(const char *));
7367 if (!reallocated) {
7368 LOGMEM;
7369 lydict_remove(mod->ctx, p[1][c]);
7370 p[1][c] = NULL;
7371 return EXIT_FAILURE;
7372 }
7373 p[1] = reallocated;
7374 p[1][c + 1] = NULL;
7375 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007376 }
7377
7378 return EXIT_SUCCESS;
7379}
7380
7381static void *
7382yin_getplace_for_extcomplex_flags(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt,
7383 uint16_t mask)
7384{
7385 void *data;
7386 struct lyext_substmt *info;
7387
7388 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7389 if (!data) {
7390 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7391 return NULL;
7392 }
7393 if (info->cardinality < LY_STMT_CARD_SOME && ((*(uint16_t *)data) & mask)) {
7394 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7395 return NULL;
7396 }
7397
7398 return data;
7399}
7400
Radek Krejcic1885952017-02-07 09:37:51 +01007401static int
7402yin_parse_extcomplex_flag(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007403 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007404 const char *val1_str, const char *val2_str, uint16_t mask,
7405 uint16_t val1, uint16_t val2, struct unres_schema *unres)
7406{
7407 uint16_t *val;
7408 const char *str;
7409
7410 val = yin_getplace_for_extcomplex_flags(node, ext, stmt, mask);
7411 if (!val) {
7412 return EXIT_FAILURE;
7413 }
7414
7415 str = lyxml_get_attr(node, "value", NULL);
7416 if (!str) {
7417 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
7418 } else if (!strcmp(val1_str, str)) {
7419 *val = *val | val1;
7420 } else if (!strcmp(val2_str, str)) {
7421 *val = *val | val2;
7422 } else {
7423 /* unknown value */
7424 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
7425 return EXIT_FAILURE;
7426 }
Radek Krejcibe336392017-02-07 10:54:24 +01007427 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007428 return EXIT_FAILURE;
7429 }
7430 return EXIT_SUCCESS;
7431}
7432
Radek Krejci8d6b7422017-02-03 14:42:13 +01007433static void **
7434yin_getplace_for_extcomplex_struct(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7435{
7436 int c;
7437 void **data, ***p = NULL;
7438 void *reallocated;
7439 struct lyext_substmt *info;
7440
7441 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7442 if (!data) {
7443 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7444 return NULL;
7445 }
7446 if (info->cardinality < LY_STMT_CARD_SOME && *data) {
7447 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7448 return NULL;
7449 }
7450
7451 c = 0;
7452 if (info->cardinality >= LY_STMT_CARD_SOME) {
7453 /* there can be multiple instances, so instead of pointer to array,
7454 * we have in data pointer to pointer to array */
7455 p = (void ***)data;
7456 data = *p;
7457 if (!data) {
7458 /* allocate initial array */
7459 *p = data = malloc(2 * sizeof(void *));
7460 } else {
7461 for (c = 0; *data; data++, c++);
7462 }
7463 }
7464
7465 if (p) {
7466 /* enlarge the array */
7467 reallocated = realloc(*p, (c + 2) * sizeof(void *));
7468 if (!reallocated) {
7469 LOGMEM;
7470 return NULL;
7471 }
7472 *p = reallocated;
7473 data = *p;
7474 data[c + 1] = NULL;
7475 }
7476
7477 return &data[c];
7478}
7479
7480int
7481lyp_yin_parse_complex_ext(struct lys_module *mod, struct lys_ext_instance_complex *ext, struct lyxml_elem *yin,
7482 struct unres_schema *unres)
7483{
7484 struct lyxml_elem *next, *node;
7485 struct lys_type **type;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007486 void **pp, *p, *reallocated;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007487 const char *value;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007488 struct lyext_substmt *info;
7489 long int v;
7490 int i;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007491
7492 LY_TREE_FOR_SAFE(yin->child, next, node) {
7493 if (!node->ns) {
7494 /* garbage */
7495 } else if (node->ns == yin->ns && (ext->flags & LYS_YINELEM) && ly_strequal(node->name, ext->def->argument, 1)) {
7496 /* we have the extension's argument */
7497 if (ext->arg_value) {
7498 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
7499 goto error;
7500 }
7501 ext->arg_value = node->content;
7502 node->content = NULL;
7503 } else if (strcmp(node->ns->value, LY_NSYIN)) {
7504 /* extension */
7505 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_SELF, 0, unres)) {
7506 goto error;
7507 }
7508 } else if (!strcmp(node->name, "description")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007509 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DESCRIPTION, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007510 goto error;
7511 }
7512 } else if (!strcmp(node->name, "reference")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007513 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REFERENCE, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007514 goto error;
7515 }
7516 } else if (!strcmp(node->name, "units")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007517 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_UNITS, 0, "name", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007518 goto error;
7519 }
7520 } else if (!strcmp(node->name, "type")) {
7521 type = (struct lys_type **)yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPE);
7522 if (!type) {
7523 goto error;
7524 }
7525 /* allocate type structure */
7526 (*type) = calloc(1, sizeof **type);
7527
7528 /* HACK for unres */
7529 (*type)->der = (struct lys_tpdf *)node;
7530 (*type)->parent = (struct lys_tpdf *)ext;
7531
7532 if (unres_schema_add_node(mod, unres, *type, UNRES_TYPE_DER_EXT, NULL) == -1) {
7533 (*type)->der = NULL;
7534 goto error;
7535 }
7536 continue; /* skip lyxml_free() */
7537 } else if (!strcmp(node->name, "if-feature")) {
7538 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_IFFEATURE);
7539 if (!pp) {
7540 goto error;
7541 }
7542 /* allocate iffeature structure */
7543 (*pp) = calloc(1, sizeof(struct lys_iffeature));
7544
7545 if (fill_yin_iffeature((struct lys_node *)ext, 0, node, *((struct lys_iffeature **)pp), unres)) {
7546 goto error;
7547 }
7548 } else if (!strcmp(node->name, "status")) {
7549 p = yin_getplace_for_extcomplex_flags(node, ext, LY_STMT_STATUS, LYS_STATUS_MASK);
7550 if (!p) {
7551 goto error;
7552 }
7553
7554 GETVAL(value, node, "value");
7555 if (!strcmp(value, "current")) {
7556 *(uint16_t*)p |= LYS_STATUS_CURR;
7557 } else if (!strcmp(value, "deprecated")) {
7558 *(uint16_t*)p |= LYS_STATUS_DEPRC;
7559 } else if (!strcmp(value, "obsolete")) {
7560 *(uint16_t*)p |= LYS_STATUS_OBSLT;
7561 } else {
7562 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
7563 goto error;
7564 }
7565
7566 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, 0, unres)) {
7567 goto error;
7568 }
Radek Krejcic1885952017-02-07 09:37:51 +01007569 } else if (!strcmp(node->name, "config")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007570 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY, "true", "false", LYS_CONFIG_MASK,
Radek Krejcic1885952017-02-07 09:37:51 +01007571 LYS_CONFIG_W | LYS_CONFIG_SET, LYS_CONFIG_R | LYS_CONFIG_SET, unres)) {
7572 goto error;
7573 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007574 } else if (!strcmp(node->name, "argument")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007575 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ARGUMENT, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007576 goto error;
7577 }
7578 } else if (!strcmp(node->name, "default")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007579 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DEFAULT, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007580 goto error;
7581 }
Radek Krejcic1885952017-02-07 09:37:51 +01007582 } else if (!strcmp(node->name, "mandatory")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007583 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY,
Radek Krejcic1885952017-02-07 09:37:51 +01007584 "true", "false", LYS_MAND_MASK, LYS_MAND_TRUE, LYS_MAND_FALSE, unres)) {
7585 goto error;
7586 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007587 } else if (!strcmp(node->name, "error-app-tag")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007588 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRTAG, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007589 goto error;
7590 }
7591 } else if (!strcmp(node->name, "error-message")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007592 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRMSG, 1, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007593 goto error;
7594 }
7595 } else if (!strcmp(node->name, "prefix")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007596 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PREFIX, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007597 goto error;
7598 }
7599 } else if (!strcmp(node->name, "namespace")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007600 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_NAMESPACE, 0, "uri", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007601 goto error;
7602 }
7603 } else if (!strcmp(node->name, "presence")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007604 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PRESENCE, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007605 goto error;
7606 }
7607 } else if (!strcmp(node->name, "revision-date")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007608 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REVISIONDATE, 0, "date", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007609 goto error;
7610 }
7611 } else if (!strcmp(node->name, "key")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007612 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_KEY, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007613 goto error;
7614 }
7615 } else if (!strcmp(node->name, "base")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007616 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BASE, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007617 goto error;
7618 }
Radek Krejcic1885952017-02-07 09:37:51 +01007619 } else if (!strcmp(node->name, "ordered-by")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007620 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_ORDEREDBY,
7621 "user", "system", LYS_USERORDERED, LYS_USERORDERED, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007622 goto error;
7623 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007624 } else if (!strcmp(node->name, "belongs-to")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007625 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BELONGSTO, 0, "module", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007626 goto error;
7627 }
7628 } else if (!strcmp(node->name, "contact")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007629 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_CONTACT, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007630 goto error;
7631 }
7632 } else if (!strcmp(node->name, "organization")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007633 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ORGANIZATION, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007634 goto error;
7635 }
7636 } else if (!strcmp(node->name, "path")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007637 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PATH, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007638 goto error;
7639 }
7640 } else if (!strcmp(node->name, "yang-version")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007641 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_VERSION, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007642 goto error;
7643 }
Radek Krejcic1885952017-02-07 09:37:51 +01007644 } else if (!strcmp(node->name, "require-instance")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007645 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_REQINSTANCE, "true", "false", unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007646 goto error;
7647 }
7648 } else if (!strcmp(node->name, "modifier")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007649 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_MODIFIER, "invert-match", NULL, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007650 goto error;
7651 }
7652 } else if (!strcmp(node->name, "yin-element")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007653 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_YINELEM, "true", "false", unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007654 goto error;
7655 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007656 } else if (!strcmp(node->name, "value")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007657 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_VALUE, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007658 goto error;
7659 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007660 } else if (!strcmp(node->name, "fraction-digits")) {
7661 p = lys_ext_complex_get_substmt(LY_STMT_DIGITS, ext, &info);
7662 if (!p) {
7663 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7664 goto error;
7665 }
7666 if (info->cardinality < LY_STMT_CARD_SOME && (*(uint8_t *)p)) {
7667 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7668 goto error;
7669 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007670 pp = NULL;
7671 if (info->cardinality >= LY_STMT_CARD_SOME) {
7672 /* there can be multiple instances */
7673 pp = p;
Radek Krejcib84686f2017-02-09 16:04:55 +01007674 i = 0;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007675 if (!(*pp)) {
7676 /* allocate initial array */
Radek Krejcib84686f2017-02-09 16:04:55 +01007677 *pp = malloc(2 * sizeof(uint8_t));
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007678 } else {
Radek Krejcib84686f2017-02-09 16:04:55 +01007679 for (i = 0; (*(uint8_t**)pp)[i]; i++);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007680 }
Radek Krejcib84686f2017-02-09 16:04:55 +01007681 p = &(*(uint8_t**)pp)[i];
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007682 }
7683
7684 GETVAL(value, node, "value");
7685 v = strtol(value, NULL, 10);
7686
7687 /* range check */
7688 if (v < 1 || v > 18) {
7689 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
7690 goto error;
7691 }
7692
7693 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, i, unres)) {
7694 goto error;
7695 }
7696
7697 /* store the value */
7698 (*(uint8_t *)p) = (uint8_t)v;
7699
7700 if (pp) {
7701 /* enlarge the array */
7702 reallocated = realloc(*pp, (i + 2) * sizeof(uint8_t*));
7703 if (!reallocated) {
7704 LOGMEM;
7705 goto error;
7706 }
7707 *pp = reallocated;
Radek Krejcib84686f2017-02-09 16:04:55 +01007708 (*(uint8_t**)pp)[i + 1] = 0;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007709 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007710 } else {
7711 LOGERR(LY_SUCCESS, "Extension's substatement \"%s\" not yet supported.", node->name);
7712 //LOGERR(LY_EINT, "Extension's substatement \"%s\" not yet supported.", node->name);
7713 //return EXIT_FAILURE;
7714 }
7715 lyxml_free(mod->ctx, node);
7716 }
7717
7718 /* TODO check for mandatory substatements */
7719 return EXIT_SUCCESS;
7720
7721error:
7722 return EXIT_FAILURE;
7723}