blob: d444d494a28c6ff8a9d702bbff9b2375b7a01f78 [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
2 * @file yin.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief YIN parser for libyang
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Radek Krejci54f6fb32016-02-24 12:56:39 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
Michal Vasko8de098c2016-02-26 10:00:25 +010011 *
Radek Krejci54f6fb32016-02-24 12:56:39 +010012 * https://opensource.org/licenses/BSD-3-Clause
Radek Krejcida04f4a2015-05-21 12:54:09 +020013 */
14
Radek Krejci812b10a2015-05-28 16:48:25 +020015#include <assert.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020016#include <ctype.h>
Radek Krejci8b4f23c2015-06-02 16:09:25 +020017#include <errno.h>
18#include <limits.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020019#include <stdint.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020020#include <stdlib.h>
21#include <string.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020022#include <stddef.h>
Michal Vasko69068852015-07-13 14:34:31 +020023#include <sys/types.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020024
Radek Krejci998a0b82015-08-17 13:14:36 +020025#include "libyang.h"
26#include "common.h"
27#include "context.h"
Radek Krejci41912fe2015-10-22 10:22:12 +020028#include "dict_private.h"
Michal Vaskofcdac172015-10-07 09:35:05 +020029#include "xpath.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020030#include "parser.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020031#include "resolve.h"
32#include "tree_internal.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020033#include "xml_internal.h"
Radek Krejciefdd0ce2015-05-26 16:48:29 +020034
Radek Krejciadb57612016-02-16 13:34:34 +010035#define GETVAL(value, node, arg) \
36 value = lyxml_get_attr(node, arg, NULL); \
37 if (!value) { \
Radek Krejci48464ed2016-03-17 15:44:09 +010038 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, arg, node->name); \
Radek Krejciadb57612016-02-16 13:34:34 +010039 goto error; \
Michal Vasko2d710f32016-02-05 12:29:21 +010040 }
Radek Krejcice7fb782015-05-29 16:52:34 +020041
Michal Vaskoe022a562016-09-27 14:24:15 +020042#define OPT_IDENT 0x01
43#define OPT_CFG_PARSE 0x02
44#define OPT_CFG_INHERIT 0x04
45#define OPT_CFG_IGNORE 0x08
46#define OPT_MODULE 0x10
Radek Krejci07d0fb92017-01-13 14:11:05 +010047static int read_yin_common(struct lys_module *, struct lys_node *, void *, LYEXT_PAR, struct lyxml_elem *, int,
48 struct unres_schema *);
Radek Krejcib388c152015-06-04 17:03:03 +020049
Radek Krejcib8048692015-08-05 13:36:34 +020050static struct lys_node *read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +010051 int options, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020052static struct lys_node *read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +010053 int options, struct unres_schema *unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +020054static struct lys_node *read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020055 LYS_NODE type, int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020056static struct lys_node *read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +010057 int options, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020058static struct lys_node *read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020059 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020060static struct lys_node *read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020061 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020062static struct lys_node *read_yin_list(struct lys_module *module,struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +010063 int options, struct unres_schema *unres);
Radek Krejcia9544502015-08-14 08:24:29 +020064static struct lys_node *read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +010065 int options, struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020066static struct lys_node *read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +010067 int options, struct unres_schema *unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +020068static struct lys_node *read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +010069 int options, struct unres_schema *unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +020070static struct lys_node *read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +010071 int options, struct unres_schema *unres);
Radek Krejci5323b492017-01-16 15:40:11 +010072static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres);
Radek Krejci74705112015-06-05 10:25:44 +020073
Radek Krejci07d0fb92017-01-13 14:11:05 +010074/*
75 * yin - the provided XML subtree is unlinked
Radek Krejci2b999ac2017-01-18 16:22:12 +010076 * ext - pointer to the storage in the parent structure to be able to update its location after realloc
Radek Krejci07d0fb92017-01-13 14:11:05 +010077 */
78int
79lyp_yin_fill_ext(void *parent, LYEXT_PAR parent_type, LYEXT_SUBSTMT substmt, uint8_t substmt_index,
Radek Krejci2b999ac2017-01-18 16:22:12 +010080 struct lys_module *module, struct lyxml_elem *yin, struct lys_ext_instance ***ext,
81 uint8_t ext_index, struct unres_schema *unres)
Radek Krejci07d0fb92017-01-13 14:11:05 +010082{
83 struct unres_ext *info;
84
85 info = malloc(sizeof *info);
Radek Krejcia8d111f2017-05-31 13:57:37 +020086 LY_CHECK_ERR_RETURN(!info, LOGMEM, EXIT_FAILURE);
Radek Krejci07d0fb92017-01-13 14:11:05 +010087 lyxml_unlink(module->ctx, yin);
88 info->data.yin = yin;
89 info->datatype = LYS_IN_YIN;
90 info->parent = parent;
Radek Krejcia7db9702017-01-20 12:55:14 +010091 info->mod = module;
Radek Krejci07d0fb92017-01-13 14:11:05 +010092 info->parent_type = parent_type;
93 info->substmt = substmt;
94 info->substmt_index = substmt_index;
Radek Krejci2b999ac2017-01-18 16:22:12 +010095 info->ext_index = ext_index;
Radek Krejci07d0fb92017-01-13 14:11:05 +010096
97 if (unres_schema_add_node(module, unres, ext, UNRES_EXT, (struct lys_node *)info) == -1) {
98 return EXIT_FAILURE;
99 }
100
101 return EXIT_SUCCESS;
102}
103
Michal Vasko0d343d12015-08-24 14:57:36 +0200104/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200105static const char *
106read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +0200107{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200108 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200109
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200110 /* there should be <text> child */
111 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
Radek Krejci218436d2016-02-10 12:54:06 +0100112 LOGERR(LY_EVALID, "Expected \"%s\" element in \"%s\" element.", name, node->name);
Radek Krejci48464ed2016-03-17 15:44:09 +0100113 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, node->name);
Radek Krejci218436d2016-02-10 12:54:06 +0100114 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200115 } else if (node->child->content) {
116 len = strlen(node->child->content);
117 return lydict_insert(ctx, node->child->content, len);
Radek Krejci218436d2016-02-10 12:54:06 +0100118 } else {
119 return lydict_insert(ctx, "", 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200120 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200121}
122
Radek Krejci8d6b7422017-02-03 14:42:13 +0100123int
124lyp_yin_parse_subnode_ext(struct lys_module *mod, void *elem, LYEXT_PAR elem_type,
Radek Krejciac00b2a2017-01-17 14:05:00 +0100125 struct lyxml_elem *yin, LYEXT_SUBSTMT type, uint8_t i, struct unres_schema *unres)
Radek Krejcie534c132016-11-23 13:32:31 +0100126{
Radek Krejci07d0fb92017-01-13 14:11:05 +0100127 void *reallocated;
128 struct lyxml_elem *next, *child;
129 int r;
130 struct lys_ext_instance ***ext;
131 uint8_t *ext_size;
Radek Krejcie534c132016-11-23 13:32:31 +0100132
Radek Krejci07d0fb92017-01-13 14:11:05 +0100133 switch (elem_type) {
134 case LYEXT_PAR_MODULE:
135 ext_size = &((struct lys_module *)elem)->ext_size;
136 ext = &((struct lys_module *)elem)->ext;
137 break;
Radek Krejci95f22ae2017-01-20 14:25:53 +0100138 case LYEXT_PAR_IMPORT:
139 ext_size = &((struct lys_import *)elem)->ext_size;
140 ext = &((struct lys_import *)elem)->ext;
141 break;
142 case LYEXT_PAR_INCLUDE:
143 ext_size = &((struct lys_include *)elem)->ext_size;
144 ext = &((struct lys_include *)elem)->ext;
145 break;
146 case LYEXT_PAR_REVISION:
147 ext_size = &((struct lys_revision *)elem)->ext_size;
148 ext = &((struct lys_revision *)elem)->ext;
149 break;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100150 case LYEXT_PAR_NODE:
151 ext_size = &((struct lys_node *)elem)->ext_size;
152 ext = &((struct lys_node *)elem)->ext;
153 break;
154 case LYEXT_PAR_IDENT:
155 ext_size = &((struct lys_ident *)elem)->ext_size;
156 ext = &((struct lys_ident *)elem)->ext;
157 break;
Radek Krejci47f7ea52017-01-23 13:14:09 +0100158 case LYEXT_PAR_TYPE:
159 ext_size = &((struct lys_type *)elem)->ext_size;
160 ext = &((struct lys_type *)elem)->ext;
161 break;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100162 case LYEXT_PAR_TYPE_BIT:
163 ext_size = &((struct lys_type_bit *)elem)->ext_size;
164 ext = &((struct lys_type_bit *)elem)->ext;
165 break;
166 case LYEXT_PAR_TYPE_ENUM:
167 ext_size = &((struct lys_type_enum *)elem)->ext_size;
168 ext = &((struct lys_type_enum *)elem)->ext;
169 break;
170 case LYEXT_PAR_TPDF:
171 ext_size = &((struct lys_tpdf *)elem)->ext_size;
172 ext = &((struct lys_tpdf *)elem)->ext;
173 break;
174 case LYEXT_PAR_EXT:
175 ext_size = &((struct lys_ext *)elem)->ext_size;
176 ext = &((struct lys_ext *)elem)->ext;
177 break;
Radek Krejci8d6b7422017-02-03 14:42:13 +0100178 case LYEXT_PAR_EXTINST:
179 ext_size = &((struct lys_ext_instance *)elem)->ext_size;
180 ext = &((struct lys_ext_instance *)elem)->ext;
181 break;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100182 case LYEXT_PAR_FEATURE:
183 ext_size = &((struct lys_feature *)elem)->ext_size;
184 ext = &((struct lys_feature *)elem)->ext;
185 break;
186 case LYEXT_PAR_REFINE:
187 ext_size = &((struct lys_refine *)elem)->ext_size;
188 ext = &((struct lys_refine *)elem)->ext;
189 break;
Radek Krejcifdc0d702017-01-23 15:58:38 +0100190 case LYEXT_PAR_RESTR:
Radek Krejcifccd1442017-01-16 10:26:57 +0100191 ext_size = &((struct lys_restr *)elem)->ext_size;
192 ext = &((struct lys_restr *)elem)->ext;
193 break;
Radek Krejci5323b492017-01-16 15:40:11 +0100194 case LYEXT_PAR_WHEN:
195 ext_size = &((struct lys_when *)elem)->ext_size;
196 ext = &((struct lys_when *)elem)->ext;
197 break;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +0100198 case LYEXT_PAR_DEVIATE:
199 ext_size = &((struct lys_deviate *)elem)->ext_size;
200 ext = &((struct lys_deviate *)elem)->ext;
201 break;
202 case LYEXT_PAR_DEVIATION:
203 ext_size = &((struct lys_deviation *)elem)->ext_size;
204 ext = &((struct lys_deviation *)elem)->ext;
205 break;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100206 default:
Radek Krejcifccd1442017-01-16 10:26:57 +0100207 LOGERR(LY_EINT, "parent type %d", elem_type);
Radek Krejcie534c132016-11-23 13:32:31 +0100208 return EXIT_FAILURE;
209 }
210
Radek Krejcifccd1442017-01-16 10:26:57 +0100211 if (type == LYEXT_SUBSTMT_SELF) {
212 /* parse for the statement self, not for the substatement */
213 child = yin;
214 next = NULL;
215 goto parseext;
216 }
217
Radek Krejci07d0fb92017-01-13 14:11:05 +0100218 LY_TREE_FOR_SAFE(yin->child, next, child) {
219 if (!strcmp(child->ns->value, LY_NSYIN)) {
220 /* skip the regular YIN nodes */
221 continue;
222 }
223
224 /* parse it as extension */
Radek Krejcifccd1442017-01-16 10:26:57 +0100225parseext:
Radek Krejci07d0fb92017-01-13 14:11:05 +0100226
227 /* first, allocate a space for the extension instance in the parent elem */
228 reallocated = realloc(*ext, (1 + (*ext_size)) * sizeof **ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200229 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM, EXIT_FAILURE);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100230 (*ext) = reallocated;
231
232 /* init memory */
233 (*ext)[(*ext_size)] = NULL;
234
235 /* parse YIN data */
Radek Krejci2b999ac2017-01-18 16:22:12 +0100236 r = lyp_yin_fill_ext(elem, elem_type, type, i, mod, child, &(*ext), (*ext_size), unres);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100237 (*ext_size)++;
238 if (r) {
239 return EXIT_FAILURE;
240 }
241
Radek Krejcifccd1442017-01-16 10:26:57 +0100242 /* done - do not free the child, it is unlinked in lyp_yin_fill_ext */
Radek Krejci07d0fb92017-01-13 14:11:05 +0100243 }
244
Radek Krejcie534c132016-11-23 13:32:31 +0100245 return EXIT_SUCCESS;
246}
247
Michal Vasko0d343d12015-08-24 14:57:36 +0200248/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200249static int
Radek Krejci9de2c042016-10-19 16:53:06 +0200250fill_yin_iffeature(struct lys_node *parent, int parent_is_feature, struct lyxml_elem *yin, struct lys_iffeature *iffeat,
251 struct unres_schema *unres)
Michal Vasko1d337e12016-02-15 12:32:04 +0100252{
Radek Krejci5323b492017-01-16 15:40:11 +0100253 int r, c_ext = 0;
Michal Vasko1d337e12016-02-15 12:32:04 +0100254 const char *value;
Radek Krejci5323b492017-01-16 15:40:11 +0100255 struct lyxml_elem *node, *next;
Michal Vasko1d337e12016-02-15 12:32:04 +0100256
257 GETVAL(value, yin, "name");
Michal Vasko97b32be2016-07-25 10:59:53 +0200258
259 if ((lys_node_module(parent)->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
260 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
Radek Krejci9ff0a922016-07-14 13:08:05 +0200261error:
Michal Vasko1d337e12016-02-15 12:32:04 +0100262 return EXIT_FAILURE;
263 }
264
Michal Vasko56d082c2016-10-25 14:00:42 +0200265 if (!(value = transform_iffeat_schema2json(parent->module, value))) {
Michal Vasko1d337e12016-02-15 12:32:04 +0100266 return EXIT_FAILURE;
267 }
268
Radek Krejci9de2c042016-10-19 16:53:06 +0200269 r = resolve_iffeature_compile(iffeat, value, parent, parent_is_feature, unres);
Michal Vasko1d337e12016-02-15 12:32:04 +0100270 lydict_remove(parent->module->ctx, value);
Radek Krejci9ff0a922016-07-14 13:08:05 +0200271 if (r) {
272 return EXIT_FAILURE;
Michal Vasko1d337e12016-02-15 12:32:04 +0100273 }
274
Radek Krejci5323b492017-01-16 15:40:11 +0100275 LY_TREE_FOR_SAFE(yin->child, next, node) {
276 if (!node->ns) {
277 /* garbage */
278 lyxml_free(parent->module->ctx, node);
279 } else if (strcmp(node->ns->value, LY_NSYIN)) {
280 /* extension */
281 c_ext++;
282 } else {
283 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "if-feature");
284 return EXIT_FAILURE;
285 }
286 }
287 if (c_ext) {
288 iffeat->ext = calloc(c_ext, sizeof *iffeat->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200289 LY_CHECK_ERR_RETURN(!iffeat->ext, LOGMEM, EXIT_FAILURE);
Radek Krejci5323b492017-01-16 15:40:11 +0100290 LY_TREE_FOR_SAFE(yin->child, next, node) {
291 /* extensions */
292 r = lyp_yin_fill_ext(iffeat, LYEXT_PAR_IDENT, 0, 0, parent->module, node,
Radek Krejci2b999ac2017-01-18 16:22:12 +0100293 &iffeat->ext, iffeat->ext_size, unres);
Radek Krejci5323b492017-01-16 15:40:11 +0100294 iffeat->ext_size++;
295 if (r) {
296 return EXIT_FAILURE;
297 }
298 }
299 }
300
Radek Krejci9ff0a922016-07-14 13:08:05 +0200301 return EXIT_SUCCESS;
Michal Vasko1d337e12016-02-15 12:32:04 +0100302}
303
304/* logs directly */
305static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200306fill_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 +0200307{
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200308 struct lyxml_elem *node, *next;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200309 const char *value;
Radek Krejci018f1f52016-08-03 16:01:20 +0200310 int rc;
Radek Krejcie534c132016-11-23 13:32:31 +0100311 int c_ftrs = 0, c_base = 0, c_ext = 0;
Radek Krejci18a44882017-01-23 13:47:29 +0100312 void *reallocated;
Radek Krejci04581c62015-05-22 21:24:00 +0200313
Michal Vasko4cfcd252015-08-03 14:31:10 +0200314 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100315 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200316
Radek Krejci07d0fb92017-01-13 14:11:05 +0100317 if (read_yin_common(module, NULL, ident, LYEXT_PAR_IDENT, yin, OPT_IDENT | OPT_MODULE, unres)) {
Radek Krejci18a44882017-01-23 13:47:29 +0100318 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200319 }
Radek Krejci04581c62015-05-22 21:24:00 +0200320
Pavol Vicand6cda452016-07-13 15:08:29 +0200321 if (dup_identities_check(ident->name, module)) {
Radek Krejci18a44882017-01-23 13:47:29 +0100322 goto error;
Pavol Vicand6cda452016-07-13 15:08:29 +0200323 }
324
Radek Krejcie534c132016-11-23 13:32:31 +0100325 LY_TREE_FOR(yin->child, node) {
326 if (strcmp(node->ns->value, LY_NSYIN)) {
327 /* extension */
328 c_ext++;
329 } else if (!strcmp(node->name, "base")) {
Radek Krejci018f1f52016-08-03 16:01:20 +0200330 if (c_base && (module->version < 2)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100331 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci18a44882017-01-23 13:47:29 +0100332 goto error;
333 }
Radek Krejci8d6b7422017-02-03 14:42:13 +0100334 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 +0100335 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200336 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200337 c_base++;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100338
Radek Krejci018f1f52016-08-03 16:01:20 +0200339 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
340 c_ftrs++;
341
342 } else {
343 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
Radek Krejci18a44882017-01-23 13:47:29 +0100344 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200345 }
346 }
347
348 if (c_base) {
349 ident->base_size = 0;
350 ident->base = calloc(c_base, sizeof *ident->base);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200351 LY_CHECK_ERR_GOTO(!ident->base, LOGMEM, error);
Radek Krejci018f1f52016-08-03 16:01:20 +0200352 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200353 if (c_ftrs) {
354 ident->iffeature = calloc(c_ftrs, sizeof *ident->iffeature);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200355 LY_CHECK_ERR_GOTO(!ident->iffeature, LOGMEM, error);
Radek Krejci018f1f52016-08-03 16:01:20 +0200356 }
Radek Krejcie534c132016-11-23 13:32:31 +0100357 if (c_ext) {
Radek Krejci18a44882017-01-23 13:47:29 +0100358 /* some extensions may be already present from the substatements */
359 reallocated = realloc(ident->ext, (c_ext + ident->ext_size) * sizeof *ident->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200360 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejci18a44882017-01-23 13:47:29 +0100361 ident->ext = reallocated;
362
363 /* init memory */
364 memset(&ident->ext[ident->ext_size], 0, c_ext * sizeof *ident->ext);
Radek Krejcie534c132016-11-23 13:32:31 +0100365 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200366
Radek Krejcie534c132016-11-23 13:32:31 +0100367 LY_TREE_FOR_SAFE(yin->child, next, node) {
368 if (strcmp(node->ns->value, LY_NSYIN)) {
369 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +0100370 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 +0100371 ident->ext_size++;
372 if (rc) {
373 goto error;
374 }
375 } else if (!strcmp(node->name, "base")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200376 GETVAL(value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100377 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100378 if (!value) {
Radek Krejci18a44882017-01-23 13:47:29 +0100379 goto error;
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200380 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100381
Radek Krejci48464ed2016-03-17 15:44:09 +0100382 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vaskoc94283a2015-10-29 09:07:20 +0100383 lydict_remove(module->ctx, value);
Radek Krejci18a44882017-01-23 13:47:29 +0100384 goto error;
Michal Vaskoc94283a2015-10-29 09:07:20 +0100385 }
386 lydict_remove(module->ctx, value);
Radek Krejci018f1f52016-08-03 16:01:20 +0200387 } else if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200388 rc = fill_yin_iffeature((struct lys_node *)ident, 0, node, &ident->iffeature[ident->iffeature_size], unres);
Radek Krejci018f1f52016-08-03 16:01:20 +0200389 ident->iffeature_size++;
390 if (rc) {
Radek Krejci18a44882017-01-23 13:47:29 +0100391 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200392 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200393 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200394 }
Radek Krejci04581c62015-05-22 21:24:00 +0200395
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200396 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200397
398error:
399 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200400}
401
Michal Vasko0d343d12015-08-24 14:57:36 +0200402/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200403static int
Radek Krejciaa9c5202017-02-15 16:10:14 +0100404read_restr_substmt(struct lys_module *module, struct lys_restr *restr, struct lyxml_elem *yin,
Radek Krejcifccd1442017-01-16 10:26:57 +0100405 struct unres_schema *unres)
Radek Krejci41726f92015-06-19 13:11:05 +0200406{
Radek Krejcifccd1442017-01-16 10:26:57 +0100407 struct lyxml_elem *child, *next;
Radek Krejci461d1622015-06-30 14:06:28 +0200408 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200409
Radek Krejcifccd1442017-01-16 10:26:57 +0100410 LY_TREE_FOR_SAFE(yin->child, next, child) {
411 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200412 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200413 continue;
Radek Krejcifccd1442017-01-16 10:26:57 +0100414 } else if (strcmp(child->ns->value, LY_NSYIN)) {
415 /* extension */
Radek Krejciaa9c5202017-02-15 16:10:14 +0100416 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100417 return EXIT_FAILURE;
418 }
419 } else if (!strcmp(child->name, "description")) {
Radek Krejci41726f92015-06-19 13:11:05 +0200420 if (restr->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100421 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200422 return EXIT_FAILURE;
423 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100424 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100425 return EXIT_FAILURE;
426 }
427 restr->dsc = read_yin_subnode(module->ctx, child, "text");
Radek Krejci41726f92015-06-19 13:11:05 +0200428 if (!restr->dsc) {
429 return EXIT_FAILURE;
430 }
431 } else if (!strcmp(child->name, "reference")) {
432 if (restr->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100433 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200434 return EXIT_FAILURE;
435 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100436 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100437 return EXIT_FAILURE;
438 }
439 restr->ref = read_yin_subnode(module->ctx, child, "text");
Radek Krejci41726f92015-06-19 13:11:05 +0200440 if (!restr->ref) {
441 return EXIT_FAILURE;
442 }
443 } else if (!strcmp(child->name, "error-app-tag")) {
444 if (restr->eapptag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100445 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200446 return EXIT_FAILURE;
447 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100448 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_ERRTAG, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100449 return EXIT_FAILURE;
450 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200451 GETVAL(value, child, "value");
Radek Krejcifccd1442017-01-16 10:26:57 +0100452 restr->eapptag = lydict_insert(module->ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200453 } else if (!strcmp(child->name, "error-message")) {
454 if (restr->emsg) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100455 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200456 return EXIT_FAILURE;
457 }
Radek Krejciaa9c5202017-02-15 16:10:14 +0100458 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_ERRMSG, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100459 return EXIT_FAILURE;
460 }
461 restr->emsg = read_yin_subnode(module->ctx, child, "value");
Radek Krejci41726f92015-06-19 13:11:05 +0200462 if (!restr->emsg) {
463 return EXIT_FAILURE;
464 }
465 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100466 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200467 return EXIT_FAILURE;
468 }
Radek Krejci41726f92015-06-19 13:11:05 +0200469 }
470
471 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200472
473error:
474 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200475}
476
Michal Vasko88c29542015-11-27 14:57:53 +0100477/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
478int
Radek Krejcib8048692015-08-05 13:36:34 +0200479fill_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 +0100480 int parenttype, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200481{
Michal Vasko0aee5c12016-06-17 14:27:26 +0200482 const char *value, *name;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200483 struct lys_node *siter;
Radek Krejcie534c132016-11-23 13:32:31 +0100484 struct lyxml_elem *next, *next2, *node, *child, exts;
Radek Krejcifccd1442017-01-16 10:26:57 +0100485 struct lys_restr **restrs, *restr;
Radek Krejci1c5890d2016-08-02 13:15:42 +0200486 struct lys_type_bit bit, *bits_sc = NULL;
487 struct lys_type_enum *enms_sc = NULL; /* shortcut */
Radek Krejcie663e012016-08-01 17:12:34 +0200488 struct lys_type *dertype;
Radek Krejcie534c132016-11-23 13:32:31 +0100489 int i, j, rc, val_set, c_ftrs, c_ext = 0;
Radek Krejcidc008d72016-02-17 13:12:14 +0100490 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200491 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200492 int64_t p, p_;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200493 size_t len;
Radek Krejcib53154b2017-07-19 09:14:13 +0200494 int in_grp = 0;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200495 char *buf, modifier;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200496
Radek Krejcie534c132016-11-23 13:32:31 +0100497 /* init */
498 memset(&exts, 0, sizeof exts);
499
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200500 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100501 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200502 if (!value) {
503 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200504 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200505
506 i = parse_identifier(value);
507 if (i < 1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100508 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100509 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200510 goto error;
511 }
512 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100513 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200514 if (value[i]) {
515 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100516 name += i;
517 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100518 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100519 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200520 goto error;
521 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200522 /* name is in dictionary, but moved */
Radek Krejci225376f2016-02-16 17:36:22 +0100523 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200524 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200525
Radek Krejci225376f2016-02-16 17:36:22 +0100526 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200527 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100528 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200529 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200530 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100531
532 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200533 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200534 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200535 lydict_remove(module->ctx, value);
Radek Krejcidc008d72016-02-17 13:12:14 +0100536 ret = EXIT_FAILURE;
537 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200538 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200539 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200540
Radek Krejci9b6aad22016-09-20 15:55:51 +0200541 if (type->base == LY_TYPE_ERR) {
Radek Krejcic13db382016-08-16 10:52:42 +0200542 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Radek Krejci9b6aad22016-09-20 15:55:51 +0200543 * 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 +0200544 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
545 if (siter) {
Radek Krejci93def382017-05-24 15:33:48 +0200546 assert(((struct lys_node_grp *)siter)->unres_count);
547 ((struct lys_node_grp *)siter)->unres_count--;
Radek Krejcic13db382016-08-16 10:52:42 +0200548 } else {
549 LOGINT;
550 goto error;
551 }
552 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200553 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200554
Radek Krejcicf509982015-12-15 09:22:44 +0100555 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100556 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejci48464ed2016-03-17 15:44:09 +0100557 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100558 return -1;
559 }
560
Radek Krejcie534c132016-11-23 13:32:31 +0100561 /* parse extension instances */
562 LY_TREE_FOR_SAFE(yin->child, next, node) {
563 if (!node->ns) {
564 /* garbage */
565 lyxml_free(module->ctx, node);
566 continue;
567 } else if (!strcmp(node->ns->value, LY_NSYIN)) {
568 /* YANG (YIN) statements - process later */
569 continue;
570 }
571
572 lyxml_unlink_elem(module->ctx, node, 2);
573 lyxml_add_child(module->ctx, &exts, node);
574 c_ext++;
575 }
576 if (c_ext) {
577 type->ext = calloc(c_ext, sizeof *type->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200578 LY_CHECK_ERR_GOTO(!type->ext, LOGMEM, error);
579
Radek Krejcie534c132016-11-23 13:32:31 +0100580 LY_TREE_FOR_SAFE(exts.child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +0100581 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 +0100582 type->ext_size++;
583 if (rc) {
584 goto error;
585 }
586 }
587 }
588
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200589 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200590 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200591 /* RFC 6020 9.7.4 - bit */
592
593 /* get bit specifications, at least one must be present */
594 LY_TREE_FOR_SAFE(yin->child, next, node) {
595 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200596 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200597 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100598 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200599 type->info.bits.count = 0;
Radek Krejci41726f92015-06-19 13:11:05 +0200600 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200601 }
602 }
Radek Krejcie663e012016-08-01 17:12:34 +0200603 dertype = &type->der->type;
604 if (!dertype->der) {
605 if (!type->info.bits.count) {
606 /* type is derived directly from buit-in bits type and bit statement is required */
607 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
608 goto error;
609 }
610 } else {
611 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
612 if (module->version < 2 && type->info.bits.count) {
613 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
614 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
615 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejci69794c62016-08-02 11:01:21 +0200616 type->info.bits.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200617 goto error;
618 }
Radek Krejciac781922015-07-09 15:35:14 +0200619 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200620
621 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200622 LY_CHECK_ERR_GOTO(!type->info.bits.bit, LOGMEM, error);
623
Radek Krejci73adb602015-07-02 18:07:40 +0200624 p = 0;
625 i = -1;
626 LY_TREE_FOR(yin->child, next) {
627 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200628 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200629
630 GETVAL(value, next, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100631 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100632 goto error;
633 }
634
Radek Krejci994b6f62015-06-18 16:47:27 +0200635 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100636 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 +0200637 type->info.bits.count = i + 1;
638 goto error;
639 }
640
Radek Krejcie663e012016-08-01 17:12:34 +0200641 if (!dertype->der) { /* directly derived type from bits built-in type */
642 /* check the name uniqueness */
643 for (j = 0; j < i; j++) {
644 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
645 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
646 type->info.bits.count = i + 1;
647 goto error;
648 }
649 }
650 } else {
651 /* restricted bits type - the name MUST be used in the base type */
652 bits_sc = dertype->info.bits.bit;
653 for (j = 0; j < dertype->info.bits.count; j++) {
654 if (ly_strequal(bits_sc[j].name, value, 1)) {
655 break;
656 }
657 }
658 if (j == dertype->info.bits.count) {
659 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci994b6f62015-06-18 16:47:27 +0200660 type->info.bits.count = i + 1;
661 goto error;
662 }
663 }
664
Radek Krejcie663e012016-08-01 17:12:34 +0200665
Radek Krejci0d70c372015-07-02 16:23:10 +0200666 p_ = -1;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100667 LY_TREE_FOR_SAFE(next->child, next2, node) {
668 if (!node->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200669 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200670 continue;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100671 } else if (strcmp(node->ns->value, LY_NSYIN)) {
672 /* extension */
Radek Krejci8d6b7422017-02-03 14:42:13 +0100673 if (lyp_yin_parse_subnode_ext(module, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +0100674 LYEXT_SUBSTMT_SELF, 0, unres)) {
675 goto error;
676 }
677 } else if (!strcmp(node->name, "position")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200678 if (p_ != -1) {
679 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
680 type->info.bits.count = i + 1;
681 goto error;
682 }
683
Radek Krejci0d70c372015-07-02 16:23:10 +0200684 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200685 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200686
687 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200688 if (p_ < 0 || p_ > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100689 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200690 type->info.bits.count = i + 1;
691 goto error;
692 }
693 type->info.bits.bit[i].pos = (uint32_t)p_;
694
Radek Krejcie663e012016-08-01 17:12:34 +0200695 if (!dertype->der) { /* directly derived type from bits built-in type */
696 /* keep the highest enum value for automatic increment */
697 if (type->info.bits.bit[i].pos >= p) {
698 p = type->info.bits.bit[i].pos;
699 p++;
700 } else {
701 /* check that the value is unique */
702 for (j = 0; j < i; j++) {
703 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
704 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
705 type->info.bits.bit[i].pos, type->info.bits.bit[i].name,
706 type->info.bits.bit[j].name);
707 type->info.bits.count = i + 1;
708 goto error;
709 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200710 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200711 }
712 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200713
Radek Krejci8d6b7422017-02-03 14:42:13 +0100714 if (lyp_yin_parse_subnode_ext(module, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +0100715 LYEXT_SUBSTMT_POSITION, 0, unres)) {
716 goto error;
717 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200718 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
719 c_ftrs++;
Radek Krejci0d70c372015-07-02 16:23:10 +0200720 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100721 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200722 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200723 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200724 }
Radek Krejcie663e012016-08-01 17:12:34 +0200725
726 if (!dertype->der) { /* directly derived type from bits built-in type */
727 if (p_ == -1) {
728 /* assign value automatically */
729 if (p > UINT32_MAX) {
730 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
731 type->info.bits.count = i + 1;
732 goto error;
733 }
734 type->info.bits.bit[i].pos = (uint32_t)p;
735 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
736 p++;
Radek Krejci994b6f62015-06-18 16:47:27 +0200737 }
Radek Krejcie663e012016-08-01 17:12:34 +0200738 } else { /* restricted bits type */
739 if (p_ == -1) {
740 /* automatically assign position from base type */
741 type->info.bits.bit[i].pos = bits_sc[j].pos;
742 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
743 } else {
744 /* check that the assigned position corresponds to the original
745 * position of the bit in the base type */
746 if (p_ != bits_sc[j].pos) {
747 /* p_ - assigned position in restricted bits
748 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
749 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
Radek Krejci541a45d2016-08-02 13:12:07 +0200750 type->info.bits.bit[i].name, bits_sc[j].pos);
Radek Krejcie663e012016-08-01 17:12:34 +0200751 type->info.bits.count = i + 1;
752 goto error;
753 }
754 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200755 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200756
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200757 /* if-features */
758 if (c_ftrs) {
759 bits_sc = &type->info.bits.bit[i];
760 bits_sc->iffeature = calloc(c_ftrs, sizeof *bits_sc->iffeature);
761 if (!bits_sc->iffeature) {
762 LOGMEM;
Radek Krejci994b6f62015-06-18 16:47:27 +0200763 type->info.bits.count = i + 1;
764 goto error;
765 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200766
767 LY_TREE_FOR(next->child, node) {
768 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200769 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200770 &bits_sc->iffeature[bits_sc->iffeature_size], unres);
771 bits_sc->iffeature_size++;
772 if (rc) {
773 type->info.bits.count = i + 1;
774 goto error;
775 }
776 }
777 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200778 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200779
780 /* keep them ordered by position */
781 j = i;
782 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
783 /* switch them */
784 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
785 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
786 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
787 j--;
788 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200789 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200790 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200791
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200792 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200793 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200794 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200795
Radek Krejcif9401c32015-06-26 16:47:36 +0200796 if (!strcmp(node->name, "range")) {
797 if (type->info.dec64.range) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100798 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200799 goto error;
800 }
801
802 GETVAL(value, node, "value");
Radek Krejcif9401c32015-06-26 16:47:36 +0200803 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200804 LY_CHECK_ERR_GOTO(!type->info.dec64.range, LOGMEM, error);
Radek Krejcif9401c32015-06-26 16:47:36 +0200805 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
806
807 /* get possible substatements */
Radek Krejciaa9c5202017-02-15 16:10:14 +0100808 if (read_restr_substmt(module, type->info.dec64.range, node, unres)) {
Radek Krejcif9401c32015-06-26 16:47:36 +0200809 goto error;
810 }
811 } else if (!strcmp(node->name, "fraction-digits")) {
812 if (type->info.dec64.dig) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100813 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200814 goto error;
815 }
816 GETVAL(value, node, "value");
817 v = strtol(value, NULL, 10);
818
819 /* range check */
820 if (v < 1 || v > 18) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100821 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200822 goto error;
823 }
824 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200825 type->info.dec64.div = 10;
826 for (i = 1; i < v; i++) {
827 type->info.dec64.div *= 10;
828 }
Radek Krejci47f7ea52017-01-23 13:14:09 +0100829
830 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +0100831 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_DIGITS, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +0100832 goto error;
833 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200834 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100835 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200836 goto error;
837 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200838 }
839
840 /* mandatory sub-statement(s) check */
841 if (!type->info.dec64.dig && !type->der->type.der) {
842 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejci48464ed2016-03-17 15:44:09 +0100843 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200844 goto error;
845 }
Radek Krejci7511f402015-07-10 09:56:30 +0200846 if (type->info.dec64.dig && type->der->type.der) {
847 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100848 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200849 goto error;
850 }
Radek Krejci4800f652016-09-08 14:02:52 +0200851
852 /* copy fraction-digits specification from parent type for easier internal use */
853 if (type->der->type.der) {
854 type->info.dec64.dig = type->der->type.info.dec64.dig;
855 type->info.dec64.div = type->der->type.info.dec64.div;
856 }
857
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200858 if (type->info.dec64.range && lyp_check_length_range(type->info.dec64.range->expr, type)) {
859 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
860 goto error;
861 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200862 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200863
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200864 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200865 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200866
Radek Krejci994b6f62015-06-18 16:47:27 +0200867 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200868 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200869
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200870 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200871 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200872 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100873 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200874 type->info.enums.count = 0;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200875 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200876 }
877 }
Radek Krejcie663e012016-08-01 17:12:34 +0200878 dertype = &type->der->type;
879 if (!dertype->der) {
880 if (!type->info.enums.count) {
881 /* type is derived directly from buit-in enumeartion type and enum statement is required */
882 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
883 goto error;
884 }
885 } else {
886 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
887 if (module->version < 2 && type->info.enums.count) {
888 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
889 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
890 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejci69794c62016-08-02 11:01:21 +0200891 type->info.enums.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200892 goto error;
893 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200894 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200895
Radek Krejci1574a8d2015-08-03 14:16:52 +0200896 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200897 LY_CHECK_ERR_GOTO(!type->info.enums.enm, LOGMEM, error);
Radek Krejcifc8d8322016-06-24 11:23:23 +0200898
Radek Krejcie663e012016-08-01 17:12:34 +0200899 v = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200900 i = -1;
901 LY_TREE_FOR(yin->child, next) {
902 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200903 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200904
905 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100906 if (!value[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100907 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
908 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100909 goto error;
910 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200911 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100912 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 +0200913 type->info.enums.count = i + 1;
914 goto error;
915 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200916
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200917 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200918 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200919 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100920 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200921 type->info.enums.count = i + 1;
922 goto error;
923 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200924
Radek Krejcie663e012016-08-01 17:12:34 +0200925 if (!dertype->der) { /* directly derived type from enumeration built-in type */
926 /* check the name uniqueness */
927 for (j = 0; j < i; j++) {
928 if (ly_strequal(type->info.enums.enm[j].name, value, 1)) {
929 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, value);
930 type->info.enums.count = i + 1;
931 goto error;
932 }
933 }
934 } else {
935 /* restricted enumeration type - the name MUST be used in the base type */
936 enms_sc = dertype->info.enums.enm;
937 for (j = 0; j < dertype->info.enums.count; j++) {
938 if (ly_strequal(enms_sc[j].name, value, 1)) {
939 break;
940 }
941 }
942 if (j == dertype->info.enums.count) {
943 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200944 type->info.enums.count = i + 1;
945 goto error;
946 }
947 }
Radek Krejci04581c62015-05-22 21:24:00 +0200948
Radek Krejcie663e012016-08-01 17:12:34 +0200949 val_set = 0;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100950 LY_TREE_FOR_SAFE(next->child, next2, node) {
951 if (!node->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200952 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200953 continue;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100954 } else if (strcmp(node->ns->value, LY_NSYIN)) {
955 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +0100956 if (lyp_yin_parse_subnode_ext(module, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +0100957 LYEXT_SUBSTMT_SELF, 0, unres)) {
958 goto error;
959 }
960 } else if (!strcmp(node->name, "value")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200961 if (val_set) {
962 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
963 type->info.enums.count = i + 1;
964 goto error;
965 }
966
Radek Krejci0d70c372015-07-02 16:23:10 +0200967 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200968 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200969
970 /* range check */
971 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100972 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200973 type->info.enums.count = i + 1;
974 goto error;
975 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200976 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200977
Radek Krejcie663e012016-08-01 17:12:34 +0200978 if (!dertype->der) { /* directly derived type from enumeration built-in type */
Pavol Vican5de389c2016-08-30 08:55:15 +0200979 if (!i) {
980 /* change value, which is assigned automatically, if first enum has value. */
Radek Krejcie663e012016-08-01 17:12:34 +0200981 v = type->info.enums.enm[i].value;
982 v++;
983 } else {
Pavol Vican5de389c2016-08-30 08:55:15 +0200984 /* keep the highest enum value for automatic increment */
985 if (type->info.enums.enm[i].value >= v) {
986 v = type->info.enums.enm[i].value;
987 v++;
988 } else {
989 /* check that the value is unique */
990 for (j = 0; j < i; j++) {
991 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
992 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
993 type->info.enums.enm[i].value, type->info.enums.enm[i].name,
994 type->info.enums.enm[j].name);
995 type->info.enums.count = i + 1;
996 goto error;
997 }
Radek Krejcie663e012016-08-01 17:12:34 +0200998 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200999 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001000 }
1001 }
Radek Krejcifc8d8322016-06-24 11:23:23 +02001002 val_set = 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001003
Radek Krejci8d6b7422017-02-03 14:42:13 +01001004 if (lyp_yin_parse_subnode_ext(module, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, node,
Radek Krejci9b15fea2017-01-23 11:31:43 +01001005 LYEXT_SUBSTMT_VALUE, 0, unres)) {
1006 goto error;
1007 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001008 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
1009 c_ftrs++;
1010
Radek Krejci0d70c372015-07-02 16:23:10 +02001011 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001012 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001013 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001014 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001015 }
Radek Krejcie663e012016-08-01 17:12:34 +02001016
1017 if (!dertype->der) { /* directly derived type from enumeration */
1018 if (!val_set) {
1019 /* assign value automatically */
1020 if (v > INT32_MAX) {
1021 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
1022 type->info.enums.count = i + 1;
1023 goto error;
1024 }
1025 type->info.enums.enm[i].value = v;
1026 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1027 v++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001028 }
Radek Krejcie663e012016-08-01 17:12:34 +02001029 } else { /* restricted enum type */
1030 if (!val_set) {
1031 /* automatically assign value from base type */
1032 type->info.enums.enm[i].value = enms_sc[j].value;
1033 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1034 } else {
1035 /* check that the assigned value corresponds to the original
1036 * value of the enum in the base type */
1037 if (v_ != enms_sc[j].value) {
1038 /* v_ - assigned value in restricted enum
1039 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
1040 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL,
Radek Krejci541a45d2016-08-02 13:12:07 +02001041 type->info.enums.enm[i].value, type->info.enums.enm[i].name, enms_sc[j].value);
Radek Krejcie663e012016-08-01 17:12:34 +02001042 type->info.enums.count = i + 1;
1043 goto error;
1044 }
1045 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001046 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001047
1048 /* if-features */
1049 if (c_ftrs) {
1050 enms_sc = &type->info.enums.enm[i];
1051 enms_sc->iffeature = calloc(c_ftrs, sizeof *enms_sc->iffeature);
1052 if (!enms_sc->iffeature) {
1053 LOGMEM;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001054 type->info.enums.count = i + 1;
1055 goto error;
1056 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001057
1058 LY_TREE_FOR(next->child, node) {
1059 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02001060 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001061 &enms_sc->iffeature[enms_sc->iffeature_size], unres);
1062 enms_sc->iffeature_size++;
1063 if (rc) {
1064 type->info.enums.count = i + 1;
1065 goto error;
1066 }
1067 }
1068 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001069 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001070
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001071 }
1072 break;
1073
1074 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +02001075 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001076
Michal Vaskof2d43962016-09-02 11:10:16 +02001077 /* get base specification, at least one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +02001078 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001079
Michal Vaskoe29c6622015-11-27 15:02:31 +01001080 if (strcmp(node->name, "base")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001081 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001082 goto error;
1083 }
Michal Vaskof2d43962016-09-02 11:10:16 +02001084
1085 GETVAL(value, yin->child, "name");
1086 /* store in the JSON format */
1087 value = transform_schema2json(module, value);
1088 if (!value) {
1089 goto error;
1090 }
1091 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
1092 lydict_remove(module->ctx, value);
Michal Vaskof2d43962016-09-02 11:10:16 +02001093 if (rc == -1) {
1094 goto error;
1095 }
Radek Krejci18a44882017-01-23 13:47:29 +01001096
Radek Krejci8d6b7422017-02-03 14:42:13 +01001097 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_BASE, 0, unres)) {
Radek Krejci18a44882017-01-23 13:47:29 +01001098 goto error;
1099 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001100 }
1101
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001102 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +02001103 if (type->der->type.der) {
Michal Vaskof2d43962016-09-02 11:10:16 +02001104 /* this is just a derived type with no base required */
Radek Krejci65c889c2015-06-22 10:17:22 +02001105 break;
1106 }
Radek Krejci48464ed2016-03-17 15:44:09 +01001107 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001108 goto error;
Pavol Vicanf0046f42016-09-07 15:11:09 +02001109 } else {
1110 if (type->der->type.der) {
1111 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
1112 goto error;
1113 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001114 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001115 if (yin->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001116 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001117 goto error;
1118 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001119 break;
1120
1121 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +02001122 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +02001123 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001124
Radek Krejciaf351422015-06-19 14:49:38 +02001125 if (!strcmp(node->name, "require-instance")) {
1126 if (type->info.inst.req) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001127 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001128 goto error;
1129 }
1130 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001131 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001132 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001133 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001134 type->info.inst.req = -1;
1135 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001136 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001137 goto error;
1138 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001139
1140 /* extensions */
Radek Krejcibe336392017-02-07 10:54:24 +01001141 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINSTANCE, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001142 goto error;
1143 }
Radek Krejciaf351422015-06-19 14:49:38 +02001144 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001145 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001146 goto error;
1147 }
Radek Krejciaf351422015-06-19 14:49:38 +02001148 }
Michal Vasko8548cf92015-07-20 15:17:53 +02001149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001150 break;
1151
Radek Krejcif2860132015-06-20 12:37:20 +02001152 case LY_TYPE_BINARY:
1153 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001154 case LY_TYPE_INT8:
1155 case LY_TYPE_INT16:
1156 case LY_TYPE_INT32:
1157 case LY_TYPE_INT64:
1158 case LY_TYPE_UINT8:
1159 case LY_TYPE_UINT16:
1160 case LY_TYPE_UINT32:
1161 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +02001162 /* RFC 6020 9.2.4 - range */
1163
1164 /* length and range are actually the same restriction, so process
1165 * them by this common code, we just need to differ the name and
1166 * structure where the information will be stored
1167 */
1168 if (type->base == LY_TYPE_BINARY) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001169 restrs = &type->info.binary.length;
Radek Krejcif2860132015-06-20 12:37:20 +02001170 name = "length";
1171 } else {
Radek Krejcifccd1442017-01-16 10:26:57 +01001172 restrs = &type->info.num.range;
Radek Krejcif2860132015-06-20 12:37:20 +02001173 name = "range";
1174 }
1175
Radek Krejci73adb602015-07-02 18:07:40 +02001176 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001177
Radek Krejcif2860132015-06-20 12:37:20 +02001178 if (!strcmp(node->name, name)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001179 if (*restrs) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001180 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001181 goto error;
1182 }
1183
1184 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +02001185 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001186 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +02001187 goto error;
1188 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001189 *restrs = calloc(1, sizeof **restrs);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001190 LY_CHECK_ERR_GOTO(!(*restrs), LOGMEM, error);
Radek Krejcifccd1442017-01-16 10:26:57 +01001191 (*restrs)->expr = lydict_insert(module->ctx, value, 0);
Radek Krejcif2860132015-06-20 12:37:20 +02001192
1193 /* get possible substatements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001194 if (read_restr_substmt(module, *restrs, node, unres)) {
Radek Krejcif2860132015-06-20 12:37:20 +02001195 goto error;
1196 }
1197 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001198 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001199 goto error;
1200 }
Radek Krejcif2860132015-06-20 12:37:20 +02001201 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001202 break;
1203
1204 case LY_TYPE_LEAFREF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02001205 /* flag resolving for later use */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001206 if (!parenttype) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001207 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
1208 if (siter) {
1209 /* just a flag - do not resolve */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001210 parenttype = 1;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001211 }
1212 }
1213
Radek Krejcidc4c1412015-06-19 15:39:54 +02001214 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +02001215 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001216
Michal Vasko88c29542015-11-27 14:57:53 +01001217 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +02001218 if (type->info.lref.path) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001219 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001220 goto error;
1221 }
1222
1223 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +02001224 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +01001225 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +02001226 if (!type->info.lref.path) {
1227 goto error;
1228 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001229
1230 /* try to resolve leafref path only when this is instantiated
1231 * leaf, so it is not:
1232 * - typedef's type,
1233 * - in grouping definition,
1234 * - just instantiated in a grouping definition,
1235 * because in those cases the nodes referenced in path might not be present
1236 * and it is not a bug. */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001237 if (!parenttype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001238 goto error;
1239 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001240
1241 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001242 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_PATH, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001243 goto error;
1244 }
Radek Krejcid6353ed2016-09-15 13:30:45 +02001245 } else if (module->version >= 2 && !strcmp(node->name, "require-instance")) {
Michal Vasko08ae53e2016-09-02 12:40:04 +02001246 if (type->info.lref.req) {
1247 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
1248 goto error;
1249 }
1250 GETVAL(value, node, "value");
1251 if (!strcmp(value, "true")) {
1252 type->info.lref.req = 1;
1253 } else if (!strcmp(value, "false")) {
1254 type->info.lref.req = -1;
1255 } else {
1256 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
1257 goto error;
1258 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001259
1260 /* extensions */
Radek Krejcibe336392017-02-07 10:54:24 +01001261 if (lyp_yin_parse_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINSTANCE, 0, unres)) {
Radek Krejci47f7ea52017-01-23 13:14:09 +01001262 goto error;
1263 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001264 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001265 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001266 goto error;
1267 }
Radek Krejci73adb602015-07-02 18:07:40 +02001268 }
1269
Radek Krejci742be352016-07-17 12:18:54 +02001270 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001271 if (!type->der->type.der) {
1272 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
1273 goto error;
1274 } else {
1275 /* copy leafref definition into the derived type */
1276 type->info.lref.path = lydict_insert(module->ctx, type->der->type.info.lref.path, 0);
1277 /* and resolve the path at the place we are (if not in grouping/typedef) */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001278 if (!parenttype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001279 goto error;
1280 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001281 }
Radek Krejci742be352016-07-17 12:18:54 +02001282 }
1283
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001284 break;
1285
1286 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +02001287 /* RFC 6020 9.4.4 - length */
1288 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +02001289 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +02001290 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001291
Radek Krejci3733a802015-06-19 13:43:21 +02001292 if (!strcmp(node->name, "length")) {
1293 if (type->info.str.length) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001294 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001295 goto error;
1296 }
1297
1298 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +02001299 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001300 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +02001301 goto error;
1302 }
1303 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001304 LY_CHECK_ERR_GOTO(!type->info.str.length, LOGMEM, error);
Radek Krejci3733a802015-06-19 13:43:21 +02001305 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
1306
Radek Krejci5fbc9162015-06-19 14:11:11 +02001307 /* get possible sub-statements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001308 if (read_restr_substmt(module, type->info.str.length, node, unres)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001309 goto error;
1310 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001311 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001312 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +02001313 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001314 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001315 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001316 goto error;
1317 }
1318 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001319 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001320 if (i) {
Radek Krejcif15cc7c2017-07-19 12:00:02 +02001321 if (!parenttype && parent && lys_ingrouping(parent)) {
Radek Krejcib53154b2017-07-19 09:14:13 +02001322 in_grp = 1;
1323 }
Radek Krejci73adb602015-07-02 18:07:40 +02001324 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vaskofcd974b2017-08-22 10:17:49 +02001325 LY_CHECK_ERR_GOTO(!type->info.str.patterns, LOGMEM, error);
1326#ifdef LY_ENABLED_CACHE
Radek Krejcib53154b2017-07-19 09:14:13 +02001327 if (!in_grp) {
1328 /* do not compile patterns in groupings */
1329 type->info.str.patterns_pcre = malloc(2 * i * sizeof *type->info.str.patterns_pcre);
Michal Vaskofcd974b2017-08-22 10:17:49 +02001330 LY_CHECK_ERR_GOTO(!type->info.str.patterns_pcre, LOGMEM, error);
Radek Krejcib53154b2017-07-19 09:14:13 +02001331 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02001332#endif
Radek Krejci73adb602015-07-02 18:07:40 +02001333 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +01001334 GETVAL(value, node, "value");
Radek Krejcib53154b2017-07-19 09:14:13 +02001335
Michal Vaskofcd974b2017-08-22 10:17:49 +02001336 if (!(module->ctx->models.flags & LY_CTX_TRUSTED)) {
1337 if (in_grp) {
1338 /* in grouping, just check the pattern syntax */
1339 if (lyp_check_pattern(value, NULL)) {
1340 goto error;
1341 }
Radek Krejcib53154b2017-07-19 09:14:13 +02001342 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02001343#ifdef LY_ENABLED_CACHE
1344 else {
1345 /* outside grouping, check syntax and precompile pattern for later use by libpcre */
1346 if (lyp_precompile_pattern(value,
1347 (pcre**)&type->info.str.patterns_pcre[type->info.str.pat_count * 2],
1348 (pcre_extra**)&type->info.str.patterns_pcre[type->info.str.pat_count * 2 + 1])) {
1349 goto error;
1350 }
Radek Krejcib53154b2017-07-19 09:14:13 +02001351 }
Michal Vaskofcd974b2017-08-22 10:17:49 +02001352#endif
Michal Vasko69068852015-07-13 14:34:31 +02001353 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001354 restr = &type->info.str.patterns[type->info.str.pat_count]; /* shortcut */
Radek Krejcib53154b2017-07-19 09:14:13 +02001355 type->info.str.pat_count++;
Michal Vasko69068852015-07-13 14:34:31 +02001356
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001357 modifier = 0x06; /* ACK */
1358 name = NULL;
Radek Krejcifccd1442017-01-16 10:26:57 +01001359 if (module->version >= 2) {
1360 LY_TREE_FOR_SAFE(node->child, next2, child) {
1361 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
1362 if (name) {
1363 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
1364 goto error;
1365 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001366
Radek Krejcifccd1442017-01-16 10:26:57 +01001367 GETVAL(name, child, "value");
1368 if (!strcmp(name, "invert-match")) {
1369 modifier = 0x15; /* NACK */
1370 } else {
1371 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
1372 goto error;
1373 }
1374 /* get extensions of the modifier */
Radek Krejci8d6b7422017-02-03 14:42:13 +01001375 if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child,
Radek Krejciaa9c5202017-02-15 16:10:14 +01001376 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
1377 goto error;
Radek Krejcifccd1442017-01-16 10:26:57 +01001378 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001379
Radek Krejcifccd1442017-01-16 10:26:57 +01001380 lyxml_free(module->ctx, child);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001381 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001382 }
1383 }
1384
1385 len = strlen(value);
1386 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Radek Krejcia8d111f2017-05-31 13:57:37 +02001387 LY_CHECK_ERR_GOTO(!buf, LOGMEM, error);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001388 buf[0] = modifier;
1389 strcpy(&buf[1], value);
1390
Radek Krejcifccd1442017-01-16 10:26:57 +01001391 restr->expr = lydict_insert_zc(module->ctx, buf);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001392
1393 /* get possible sub-statements */
Radek Krejciaa9c5202017-02-15 16:10:14 +01001394 if (read_restr_substmt(module, restr, node, unres)) {
Radek Krejci5fbc9162015-06-19 14:11:11 +02001395 goto error;
1396 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001397 }
1398 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001399 break;
1400
1401 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001402 /* RFC 6020 7.4 - type */
1403 /* count number of types in union */
1404 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001405 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001406
Radek Krejcie4c366b2015-07-02 10:11:31 +02001407 if (!strcmp(node->name, "type")) {
Radek Krejci038d5d92016-09-12 15:07:15 +02001408 if (type->der->type.der) {
1409 /* type can be a substatement only in "union" type, not in derived types */
1410 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "derived type");
1411 goto error;
1412 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001413 i++;
1414 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001415 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001416 goto error;
1417 }
1418 }
1419
Radek Krejci038d5d92016-09-12 15:07:15 +02001420 if (!i && !type->der->type.der) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001421 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001422 goto error;
1423 }
1424
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001425 /* inherit instid presence information */
1426 if ((type->der->type.base == LY_TYPE_UNION) && type->der->type.info.uni.has_ptr_type) {
1427 type->info.uni.has_ptr_type = 1;
1428 }
1429
Radek Krejcie4c366b2015-07-02 10:11:31 +02001430 /* allocate array for union's types ... */
Michal Vaskoadeddfc2017-06-30 13:12:42 +02001431 if (i) {
1432 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
1433 LY_CHECK_ERR_GOTO(!type->info.uni.types, LOGMEM, error);
1434 }
Radek Krejcia8d111f2017-05-31 13:57:37 +02001435
Radek Krejcie4c366b2015-07-02 10:11:31 +02001436 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001437 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +01001438 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci8d6b7422017-02-03 14:42:13 +01001439 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], parenttype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +01001440 if (!rc) {
1441 type->info.uni.count++;
1442
Radek Krejci7de36cf2016-09-12 16:18:50 +02001443 if (module->version < 2) {
1444 /* union's type cannot be empty or leafref */
1445 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
1446 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
1447 rc = -1;
1448 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
1449 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
1450 rc = -1;
1451 }
Michal Vasko88c29542015-11-27 14:57:53 +01001452 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001453
1454 if ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_INST)
1455 || (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF)) {
1456 type->info.uni.has_ptr_type = 1;
1457 }
Michal Vasko88c29542015-11-27 14:57:53 +01001458 }
1459 if (rc) {
1460 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
1461 for (i = 0; i < type->info.uni.count; ++i) {
Radek Krejci5138e9f2017-04-12 13:10:46 +02001462 lys_type_free(module->ctx, &type->info.uni.types[i], NULL);
Michal Vasko88c29542015-11-27 14:57:53 +01001463 }
1464 free(type->info.uni.types);
1465 type->info.uni.types = NULL;
1466 type->info.uni.count = 0;
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001467 type->info.uni.has_ptr_type = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +02001468 type->der = NULL;
1469 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +01001470
1471 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +01001472 ret = EXIT_FAILURE;
Michal Vasko88c29542015-11-27 14:57:53 +01001473 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001474 goto error;
1475 }
Michal Vasko88c29542015-11-27 14:57:53 +01001476 }
1477 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001478
Michal Vasko88c29542015-11-27 14:57:53 +01001479 case LY_TYPE_BOOL:
1480 case LY_TYPE_EMPTY:
1481 /* no sub-statement allowed */
Radek Krejcie534c132016-11-23 13:32:31 +01001482 if (yin->child) {
1483 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->child->name);
1484 goto error;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001485 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001486 break;
1487
1488 default:
Michal Vasko88c29542015-11-27 14:57:53 +01001489 LOGINT;
1490 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001491 }
1492
1493 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001494
1495error:
Radek Krejcidc008d72016-02-17 13:12:14 +01001496 if (type->module_name) {
1497 lydict_remove(module->ctx, type->module_name);
1498 type->module_name = NULL;
1499 }
Radek Krejcie534c132016-11-23 13:32:31 +01001500 lyxml_free_withsiblings(module->ctx, exts.child);
1501
Radek Krejcidc008d72016-02-17 13:12:14 +01001502 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001503}
1504
Michal Vasko0d343d12015-08-24 14:57:36 +02001505/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001506static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01001507fill_yin_typedef(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_tpdf *tpdf,
1508 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001509{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001510 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +01001511 struct lyxml_elem *node, *next;
Radek Krejcie534c132016-11-23 13:32:31 +01001512 int rc, has_type = 0, c_ext = 0;
Radek Krejci59a349f2017-01-24 10:14:31 +01001513 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001514
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001515 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001516 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001517 goto error;
1518 }
1519 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001520
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001521 /* generic part - status, description, reference */
Radek Krejci07d0fb92017-01-13 14:11:05 +01001522 if (read_yin_common(module, NULL, tpdf, LYEXT_PAR_TPDF, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001523 goto error;
1524 }
Radek Krejcieac35532015-05-31 19:09:15 +02001525
Michal Vasko88c29542015-11-27 14:57:53 +01001526 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejcie534c132016-11-23 13:32:31 +01001527 if (strcmp(node->ns->value, LY_NSYIN)) {
1528 /* extension */
1529 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02001530 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01001531 } else if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001532 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001533 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001534 goto error;
1535 }
Michal Vasko88c29542015-11-27 14:57:53 +01001536 /* HACK for unres */
1537 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001538 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001539 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001540 goto error;
1541 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001542 has_type = 1;
Radek Krejcie534c132016-11-23 13:32:31 +01001543
Radek Krejci07d0fb92017-01-13 14:11:05 +01001544 /* 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 +01001545 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001546 } else if (!strcmp(node->name, "default")) {
1547 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001548 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001549 goto error;
1550 }
1551 GETVAL(value, node, "value");
1552 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001553
Radek Krejci8d6b7422017-02-03 14:42:13 +01001554 if (lyp_yin_parse_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001555 goto error;
1556 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001557 } else if (!strcmp(node->name, "units")) {
1558 if (tpdf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001559 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001560 goto error;
1561 }
1562 GETVAL(value, node, "name");
1563 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001564
Radek Krejci8d6b7422017-02-03 14:42:13 +01001565 if (lyp_yin_parse_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001566 goto error;
1567 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001568 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001569 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001570 goto error;
1571 }
Radek Krejcie534c132016-11-23 13:32:31 +01001572
1573 lyxml_free(module->ctx, node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001574 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001575
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001576 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001577 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001578 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001579 goto error;
1580 }
Radek Krejcieac35532015-05-31 19:09:15 +02001581
Michal Vasko478c4652016-07-21 12:55:01 +02001582 /* check default value (if not defined, there still could be some restrictions
1583 * that need to be checked against a default value from a derived type) */
Radek Krejciab08f0f2017-03-09 16:37:15 +01001584 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPEDEF_DFLT, (struct lys_node *)(&tpdf->dflt)) == -1) {
Michal Vasko478c4652016-07-21 12:55:01 +02001585 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001586 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001587
Radek Krejcie534c132016-11-23 13:32:31 +01001588 /* finish extensions parsing */
1589 if (c_ext) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001590 /* some extensions may be already present from the substatements */
1591 reallocated = realloc(tpdf->ext, (c_ext + tpdf->ext_size) * sizeof *tpdf->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001592 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejci59a349f2017-01-24 10:14:31 +01001593 tpdf->ext = reallocated;
1594
1595 /* init memory */
1596 memset(&tpdf->ext[tpdf->ext_size], 0, c_ext * sizeof *tpdf->ext);
1597
Radek Krejcie534c132016-11-23 13:32:31 +01001598 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001599 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 +01001600 tpdf->ext_size++;
1601 if (rc) {
1602 goto error;
1603 }
1604 }
1605 }
1606
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001607 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001608
1609error:
1610
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001611 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001612}
1613
Radek Krejcia1a6b762016-11-14 09:53:38 +09001614static int
Radek Krejcie534c132016-11-23 13:32:31 +01001615fill_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 +09001616{
1617 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01001618 struct lyxml_elem *child, *node, *next, *next2;
1619 int c_ext = 0, rc;
Radek Krejci1fb02182017-01-24 11:20:55 +01001620 void *reallocated;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001621
1622 GETVAL(value, yin, "name");
1623
1624 if (lyp_check_identifier(value, LY_IDENT_EXTENSION, module, NULL)) {
1625 goto error;
1626 }
1627 ext->name = lydict_insert(module->ctx, value, strlen(value));
1628
Radek Krejci07d0fb92017-01-13 14:11:05 +01001629 if (read_yin_common(module, NULL, ext, LYEXT_PAR_EXT, yin, OPT_MODULE, unres)) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09001630 goto error;
1631 }
1632
Radek Krejcie534c132016-11-23 13:32:31 +01001633 LY_TREE_FOR_SAFE(yin->child, next, node) {
1634 if (strcmp(node->ns->value, LY_NSYIN)) {
1635 /* possible extension instance */
1636 c_ext++;
1637 } else if (!strcmp(node->name, "argument")) {
1638 /* argument */
1639 GETVAL(value, node, "name");
1640 ext->argument = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci8d6b7422017-02-03 14:42:13 +01001641 if (lyp_yin_parse_subnode_ext(module, ext, LYEXT_PAR_EXT, node, LYEXT_SUBSTMT_ARGUMENT, 0, unres)) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001642 goto error;
1643 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09001644
Radek Krejcia1a6b762016-11-14 09:53:38 +09001645 /* yin-element */
Radek Krejcie534c132016-11-23 13:32:31 +01001646 LY_TREE_FOR_SAFE(node->child, next2, child) {
1647 if (child->ns == node->ns && !strcmp(child->name, "yin-element")) {
1648 GETVAL(value, child, "value");
1649 if (ly_strequal(value, "true", 0)) {
1650 ext->flags |= LYS_YINELEM;
1651 }
Radek Krejci1fb02182017-01-24 11:20:55 +01001652
Radek Krejci8d6b7422017-02-03 14:42:13 +01001653 if (lyp_yin_parse_subnode_ext(module, ext, LYEXT_PAR_EXT, child, LYEXT_SUBSTMT_YINELEM, 0, unres)) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001654 goto error;
1655 }
Radek Krejcie534c132016-11-23 13:32:31 +01001656 } else if (child->ns) {
1657 /* unexpected YANG statement */
1658 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->name);
1659 goto error;
1660 } /* else garbage, but save resource needed for unlinking */
Radek Krejcia1a6b762016-11-14 09:53:38 +09001661 }
1662
Radek Krejcie534c132016-11-23 13:32:31 +01001663 lyxml_free(module->ctx, node);
1664 } else {
1665 /* unexpected YANG statement */
1666 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->name);
1667 goto error;
1668 }
1669 }
1670
1671 if (c_ext) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001672 /* some extensions may be already present from the substatements */
1673 reallocated = realloc(ext->ext, (c_ext + ext->ext_size) * sizeof *ext->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001674 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejci1fb02182017-01-24 11:20:55 +01001675 ext->ext = reallocated;
1676
1677 /* init memory */
1678 memset(&ext->ext[ext->ext_size], 0, c_ext * sizeof *ext->ext);
1679
1680 /* process the extension instances of the extension itself */
Radek Krejcie534c132016-11-23 13:32:31 +01001681 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001682 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 +01001683 ext->ext_size++;
1684 if (rc) {
1685 goto error;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001686 }
1687 }
1688 }
1689
Radek Krejci0a498f82017-01-04 16:24:15 +01001690 /* search for plugin */
1691 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 +09001692
1693 return EXIT_SUCCESS;
1694
1695error:
1696 return EXIT_FAILURE;
1697}
1698
Michal Vasko0d343d12015-08-24 14:57:36 +02001699/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001700static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001701fill_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 +02001702{
1703 const char *value;
1704 struct lyxml_elem *child, *next;
Radek Krejcie534c132016-11-23 13:32:31 +01001705 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci5323b492017-01-16 15:40:11 +01001706 void *reallocated;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001707
Radek Krejcib05774c2015-06-18 13:52:59 +02001708 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001709 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001710 goto error;
1711 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001712 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001713 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001714
Radek Krejci07d0fb92017-01-13 14:11:05 +01001715 if (read_yin_common(module, NULL, f, LYEXT_PAR_FEATURE, yin, 0, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001716 goto error;
1717 }
1718
Radek Krejcie534c132016-11-23 13:32:31 +01001719 LY_TREE_FOR(yin->child, child) {
1720 if (strcmp(child->ns->value, LY_NSYIN)) {
1721 /* extension */
1722 c_ext++;
1723 } else if (!strcmp(child->name, "if-feature")) {
1724 c_ftrs++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001725 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001726 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001727 goto error;
1728 }
1729 }
1730
Radek Krejcie534c132016-11-23 13:32:31 +01001731 if (c_ftrs) {
1732 f->iffeature = calloc(c_ftrs, sizeof *f->iffeature);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001733 LY_CHECK_ERR_GOTO(!f->iffeature, LOGMEM, error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001734 }
Radek Krejcie534c132016-11-23 13:32:31 +01001735 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01001736 /* some extensions may be already present from the substatements */
1737 reallocated = realloc(f->ext, (c_ext + f->ext_size) * sizeof *f->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001738 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejci5323b492017-01-16 15:40:11 +01001739 f->ext = reallocated;
1740
1741 /* init memory */
1742 memset(&f->ext[f->ext_size], 0, c_ext * sizeof *f->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001743 }
1744
Radek Krejcie534c132016-11-23 13:32:31 +01001745 LY_TREE_FOR_SAFE(yin->child, next, child) {
1746 if (strcmp(child->ns->value, LY_NSYIN)) {
1747 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01001748 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 +01001749 f->ext_size++;
1750 if (ret) {
1751 goto error;
1752 }
1753 } else { /* if-feature */
1754 ret = fill_yin_iffeature((struct lys_node *)f, 1, child, &f->iffeature[f->iffeature_size], unres);
1755 f->iffeature_size++;
1756 if (ret) {
1757 goto error;
1758 }
1759 }
1760 }
1761
Radek Krejcic79c6b12016-07-26 15:11:49 +02001762 /* check for circular dependencies */
1763 if (f->iffeature_size) {
1764 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1765 goto error;
1766 }
1767 }
1768
Radek Krejci3cf9e222015-06-18 11:37:50 +02001769 return EXIT_SUCCESS;
1770
1771error:
1772
1773 return EXIT_FAILURE;
1774}
1775
Michal Vasko0d343d12015-08-24 14:57:36 +02001776/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001777static int
Radek Krejcifccd1442017-01-16 10:26:57 +01001778fill_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 +02001779{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001780 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001781
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001782 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001783 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001784 if (!must->expr) {
1785 goto error;
1786 }
Radek Krejci800af702015-06-02 13:46:01 +02001787
Radek Krejciaa9c5202017-02-15 16:10:14 +01001788 return read_restr_substmt(module, must, yin, unres);
Radek Krejci800af702015-06-02 13:46:01 +02001789
Michal Vasko77dc5652016-02-15 12:32:42 +01001790error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001791 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001792}
1793
Radek Krejci581ce772015-11-10 17:22:40 +01001794static int
Radek Krejci7417a082017-02-16 11:07:59 +01001795fill_yin_revision(struct lys_module *module, struct lyxml_elem *yin, struct lys_revision *rev,
1796 struct unres_schema *unres)
1797{
1798 struct lyxml_elem *next, *child;
1799 const char *value;
1800
1801 GETVAL(value, yin, "date");
1802 if (lyp_check_date(value)) {
1803 goto error;
1804 }
1805 memcpy(rev->date, value, LY_REV_SIZE - 1);
1806
1807 LY_TREE_FOR_SAFE(yin->child, next, child) {
1808 if (!child->ns) {
1809 /* garbage */
1810 continue;
1811 } else if (strcmp(child->ns->value, LY_NSYIN)) {
1812 /* possible extension instance */
1813 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1814 child, LYEXT_SUBSTMT_SELF, 0, unres)) {
1815 goto error;
1816 }
1817 } else if (!strcmp(child->name, "description")) {
1818 if (rev->dsc) {
1819 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
1820 goto error;
1821 }
1822 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1823 child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
1824 goto error;
1825 }
1826 rev->dsc = read_yin_subnode(module->ctx, child, "text");
1827 if (!rev->dsc) {
1828 goto error;
1829 }
1830 } else if (!strcmp(child->name, "reference")) {
1831 if (rev->ref) {
1832 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
1833 goto error;
1834 }
1835 if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
1836 child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
1837 goto error;
1838 }
1839 rev->ref = read_yin_subnode(module->ctx, child, "text");
1840 if (!rev->ref) {
1841 goto error;
1842 }
1843 } else {
1844 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1845 goto error;
1846 }
1847 }
1848
1849 return EXIT_SUCCESS;
1850
1851error:
1852 return EXIT_FAILURE;
1853}
1854
1855static int
Michal Vasko88c29542015-11-27 14:57:53 +01001856fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1857 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001858{
Radek Krejci1a9c3612017-04-24 14:49:43 +02001859 int i, j, ret = EXIT_FAILURE;
1860 const char *orig;
Radek Krejci2449b392017-04-25 09:37:16 +02001861 char *value, *vaux, *start = NULL, c;
Radek Krejcid09d1a52016-08-11 14:05:45 +02001862 struct unres_list_uniq *unique_info;
Radek Krejci581ce772015-11-10 17:22:40 +01001863
1864 /* get unique value (list of leafs supposed to be unique */
Radek Krejci1a9c3612017-04-24 14:49:43 +02001865 GETVAL(orig, yin, "tag");
Radek Krejci581ce772015-11-10 17:22:40 +01001866
1867 /* count the number of unique leafs in the value */
Radek Krejci1a9c3612017-04-24 14:49:43 +02001868 start = value = vaux = strdup(orig);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001869 LY_CHECK_ERR_GOTO(!vaux, LOGMEM, error);
Radek Krejci581ce772015-11-10 17:22:40 +01001870 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001871 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001872 while (isspace(*vaux)) {
1873 vaux++;
1874 }
1875 }
1876 unique->expr_size++;
1877 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001878 LY_CHECK_ERR_GOTO(!unique->expr, LOGMEM, error);
Radek Krejci581ce772015-11-10 17:22:40 +01001879
1880 for (i = 0; i < unique->expr_size; i++) {
1881 vaux = strpbrk(value, " \t\n");
Radek Krejci1a9c3612017-04-24 14:49:43 +02001882 if (vaux) {
1883 c = *vaux;
1884 *vaux = '\0';
Radek Krejci581ce772015-11-10 17:22:40 +01001885 }
1886
1887 /* store token into unique structure */
Radek Krejci1a9c3612017-04-24 14:49:43 +02001888 unique->expr[i] = transform_schema2json(module, value);
1889 if (vaux) {
1890 *vaux = c;
1891 }
Radek Krejci581ce772015-11-10 17:22:40 +01001892
1893 /* check that the expression does not repeat */
1894 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001895 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001896 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1897 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001898 goto error;
1899 }
1900 }
1901
1902 /* try to resolve leaf */
1903 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001904 unique_info = malloc(sizeof *unique_info);
Radek Krejcia8d111f2017-05-31 13:57:37 +02001905 LY_CHECK_ERR_GOTO(!unique_info, LOGMEM, error);
Radek Krejcid09d1a52016-08-11 14:05:45 +02001906 unique_info->list = parent;
1907 unique_info->expr = unique->expr[i];
1908 unique_info->trg_type = &unique->trg_type;
1909 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1){
Pavol Vican18b10212016-04-11 15:41:52 +02001910 goto error;
1911 }
Radek Krejci581ce772015-11-10 17:22:40 +01001912 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001913 if (resolve_unique(parent, unique->expr[i], &unique->trg_type)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001914 goto error;
1915 }
1916 }
1917
1918 /* move to next token */
1919 value = vaux;
Radek Krejci1a9c3612017-04-24 14:49:43 +02001920 while(value && isspace(*value)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001921 value++;
1922 }
1923 }
1924
Radek Krejci1a9c3612017-04-24 14:49:43 +02001925 ret = EXIT_SUCCESS;
Radek Krejci581ce772015-11-10 17:22:40 +01001926
1927error:
Radek Krejci1a9c3612017-04-24 14:49:43 +02001928 free(start);
1929 return ret;
Radek Krejci581ce772015-11-10 17:22:40 +01001930}
1931
Michal Vasko0d343d12015-08-24 14:57:36 +02001932/* logs directly
1933 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001934 * type: 0 - min, 1 - max
1935 */
1936static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001937deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001938{
1939 const char *value;
1940 char *endptr;
1941 unsigned long val;
Pavol Vican09adcc32016-08-25 10:51:36 +02001942 uint32_t *ui32val, *min, *max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001943
Michal Vaskof7e57d52016-03-07 11:31:09 +01001944 /* del min/max is forbidden */
1945 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001946 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001947 goto error;
1948 }
1949
Radek Krejcieb00f512015-07-01 16:44:58 +02001950 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001951 if (target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001952 max = &((struct lys_node_leaflist *)target)->max;
1953 min = &((struct lys_node_leaflist *)target)->min;
Radek Krejci76512572015-08-04 09:47:08 +02001954 } else if (target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001955 max = &((struct lys_node_list *)target)->max;
1956 min = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001957 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001958 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1959 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001960 goto error;
1961 }
1962
1963 GETVAL(value, node, "value");
1964 while (isspace(value[0])) {
1965 value++;
1966 }
1967
Radek Krejci0d7b2472016-02-12 11:11:03 +01001968 if (type && !strcmp(value, "unbounded")) {
1969 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001970 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001971 ui32val = max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001972 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001973 /* convert it to uint32_t */
1974 errno = 0;
1975 endptr = NULL;
1976 val = strtoul(value, &endptr, 10);
1977 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001978 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001979 goto error;
1980 }
1981 if (type) {
1982 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001983 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001984 ui32val = max;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001985 } else {
1986 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001987 d->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001988 ui32val = min;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001989 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001990 }
1991
1992 if (d->mod == LY_DEVIATE_ADD) {
1993 /* check that there is no current value */
1994 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001995 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1996 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001997 goto error;
1998 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001999 } else if (d->mod == LY_DEVIATE_RPL) {
2000 /* unfortunately, there is no way to check reliably that there
2001 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02002002 }
2003
Michal Vaskof7e57d52016-03-07 11:31:09 +01002004 /* add (already checked) and replace */
2005 /* set new value specified in deviation */
2006 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02002007
Pavol Vican09adcc32016-08-25 10:51:36 +02002008 /* check min-elements is smaller than max-elements */
2009 if (*max && *min > *max) {
2010 if (type) {
Radek Krejci73f96012016-10-03 13:53:53 +02002011 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "max-elements");
Pavol Vican09adcc32016-08-25 10:51:36 +02002012 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
2013 } else {
Radek Krejci73f96012016-10-03 13:53:53 +02002014 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "min-elements");
Pavol Vican09adcc32016-08-25 10:51:36 +02002015 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
2016 }
2017 goto error;
2018 }
2019
Radek Krejcieb00f512015-07-01 16:44:58 +02002020 return EXIT_SUCCESS;
2021
2022error:
2023
2024 return EXIT_FAILURE;
2025}
2026
Michal Vasko0d343d12015-08-24 14:57:36 +02002027/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002028static int
Michal Vasko88c29542015-11-27 14:57:53 +01002029fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
2030 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02002031{
2032 const char *value, **stritem;
Radek Krejcie534c132016-11-23 13:32:31 +01002033 struct lyxml_elem *next, *next2, *child, *develem;
2034 int c_dev = 0, c_must, c_uniq, c_dflt, c_ext = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002035 int f_min = 0, f_max = 0; /* flags */
Radek Krejci6bd2c022017-02-01 15:04:49 +01002036 int i, j, k, rc;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002037 unsigned int u;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002038 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02002039 struct lys_deviate *d = NULL;
Radek Krejcie00d2312016-08-12 15:27:49 +02002040 struct lys_node *node = NULL, *parent, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002041 struct lys_node_choice *choice = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002042 struct lys_node_leaf *leaf = NULL;
Michal Vasko50576712017-07-28 12:28:33 +02002043 struct ly_set *dflt_check = ly_set_new(), *set;
Radek Krejcib8048692015-08-05 13:36:34 +02002044 struct lys_node_list *list = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002045 struct lys_node_leaflist *llist = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002046 struct lys_type *t = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002047 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002048 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01002049 struct unres_schema tmp_unres;
Radek Krejci27fe55e2016-09-13 17:13:35 +02002050 struct lys_module *mod;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002051 void *reallocated;
Radek Krejcieb00f512015-07-01 16:44:58 +02002052
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002053 ctx = module->ctx;
2054
Radek Krejcieb00f512015-07-01 16:44:58 +02002055 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002056 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002057 if (!dev->target_name) {
2058 goto error;
2059 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002060
2061 /* resolve target node */
Michal Vasko50576712017-07-28 12:28:33 +02002062 rc = resolve_schema_nodeid(dev->target_name, NULL, module, &set, 0, 1);
2063 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002064 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Michal Vasko50576712017-07-28 12:28:33 +02002065 ly_set_free(set);
Radek Krejcieb00f512015-07-01 16:44:58 +02002066 goto error;
2067 }
Michal Vasko50576712017-07-28 12:28:33 +02002068 dev_target = set->set.s[0];
2069 ly_set_free(set);
2070
Radek Krejcic4283442016-04-22 09:19:27 +02002071 if (dev_target->module == lys_main_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002072 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
2073 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002074 goto error;
2075 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002076
2077 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01002078 if (!child->ns ) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002079 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002080 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002081 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01002082 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2083 /* extension */
2084 c_ext++;
2085 continue;
2086 } else if (!strcmp(child->name, "description")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002087 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002088 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002089 goto error;
2090 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002091 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002092 goto error;
2093 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002094 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002095 if (!dev->dsc) {
2096 goto error;
2097 }
2098 } else if (!strcmp(child->name, "reference")) {
2099 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002100 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002101 goto error;
2102 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002103 if (lyp_yin_parse_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002104 goto error;
2105 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002106 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002107 if (!dev->ref) {
2108 goto error;
2109 }
2110 } else if (!strcmp(child->name, "deviate")) {
2111 c_dev++;
2112
Michal Vasko345da0a2015-12-02 10:35:55 +01002113 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02002114 * further processed later
2115 */
2116 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02002117
Radek Krejcieb00f512015-07-01 16:44:58 +02002118 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002119 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002120 goto error;
2121 }
2122
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002123 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02002124 }
2125
2126 if (c_dev) {
2127 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002128 LY_CHECK_ERR_GOTO(!dev->deviate, LOGMEM, error);
Pavol Vican09adcc32016-08-25 10:51:36 +02002129 } else {
2130 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
2131 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002132 }
Radek Krejcie534c132016-11-23 13:32:31 +01002133 if (c_ext) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002134 /* some extensions may be already present from the substatements */
2135 reallocated = realloc(dev->ext, (c_ext + dev->ext_size) * sizeof *dev->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002136 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002137 dev->ext = reallocated;
Radek Krejcieb00f512015-07-01 16:44:58 +02002138
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002139 /* init memory */
2140 memset(&dev->ext[dev->ext_size], 0, c_ext * sizeof *dev->ext);
2141 }
Radek Krejcie534c132016-11-23 13:32:31 +01002142
2143 LY_TREE_FOR_SAFE(yin->child, next, develem) {
2144 if (strcmp(develem->ns->value, LY_NSYIN)) {
2145 /* deviation's extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01002146 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 +01002147 dev->ext_size++;
2148 if (rc) {
2149 goto error;
2150 }
2151 continue;
2152 }
2153
2154 /* deviate */
Radek Krejcieb00f512015-07-01 16:44:58 +02002155 /* init */
2156 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002157 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002158 c_must = 0;
2159 c_uniq = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002160 c_dflt = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01002161 c_ext = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002162
2163 /* get deviation type */
2164 GETVAL(value, develem, "value");
2165 if (!strcmp(value, "not-supported")) {
2166 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002167 /* no other deviate statement is expected,
Radek Krejci5b917642015-07-02 09:03:13 +02002168 * not-supported deviation must be the only deviation of the target
2169 */
2170 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002171 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2172 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02002173 goto error;
2174 }
2175
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002176 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02002177 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
2178 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
2179 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002180 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2181 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002182 goto error;
2183 }
2184 }
2185 }
Radek Krejci5b917642015-07-02 09:03:13 +02002186
Michal Vaskoff006c12016-02-17 11:15:19 +01002187 /* unlink and store the original node */
Radek Krejci30bfcd22017-01-27 16:54:48 +01002188 parent = dev_target->parent;
Michal Vaskoff006c12016-02-17 11:15:19 +01002189 lys_node_unlink(dev_target);
Radek Krejci30bfcd22017-01-27 16:54:48 +01002190 if (parent && parent->nodetype == LYS_AUGMENT) {
2191 /* hack for augment, because when the original will be sometime reconnected back, we actually need
2192 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
2193 * path), so we need to remember the augment as an addition */
2194 dev_target->parent = parent;
2195 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002196 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02002197
Radek Krejcieb00f512015-07-01 16:44:58 +02002198 } else if (!strcmp(value, "add")) {
2199 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
2200 } else if (!strcmp(value, "replace")) {
2201 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
2202 } else if (!strcmp(value, "delete")) {
2203 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
2204 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002205 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002206 goto error;
2207 }
2208 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01002209 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002210
Michal Vaskoff006c12016-02-17 11:15:19 +01002211 /* store a shallow copy of the original node */
2212 if (!dev->orig_node) {
2213 memset(&tmp_unres, 0, sizeof tmp_unres);
Radek Krejci6ff885d2017-01-03 14:06:22 +01002214 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, &tmp_unres, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01002215 /* just to be safe */
2216 if (tmp_unres.count) {
2217 LOGINT;
2218 goto error;
2219 }
2220 }
2221
Radek Krejcieb00f512015-07-01 16:44:58 +02002222 /* process deviation properties */
Radek Krejcie534c132016-11-23 13:32:31 +01002223 LY_TREE_FOR_SAFE(develem->child, next2, child) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002224 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002225 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002226 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002227 continue;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002228 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2229 /* extensions */
2230 c_ext++;
2231 } else if (d->mod == LY_DEVIATE_NO) {
2232 /* no YIN substatement expected in this case */
2233 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2234 goto error;
2235 } else if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002236 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002237 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002238 goto error;
2239 }
2240
2241 /* for we deviate from RFC 6020 and allow config property even it is/is not
2242 * specified in the target explicitly since config property inherits. So we expect
2243 * that config is specified in every node. But for delete, we check that the value
2244 * is the same as here in deviation
2245 */
2246 GETVAL(value, child, "value");
2247 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002248 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02002249 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002250 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02002251 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002252 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002253 goto error;
2254 }
2255
2256 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002257 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002258 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002259 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002260 } else { /* add and replace are the same in this case */
2261 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01002262 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002263
2264 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01002265 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002266 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002267
Radek Krejci8d6b7422017-02-03 14:42:13 +01002268 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002269 goto error;
2270 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002271 } else if (!strcmp(child->name, "default")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002272 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 +01002273 goto error;
2274 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002275 c_dflt++;
2276
2277 /* check target node type */
2278 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
2279 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2280 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
2281 goto error;
2282 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
2283 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2284 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
2285 goto error;
2286 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
2287 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2288 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002289 goto error;
2290 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002291
Radek Krejcid5a5c282016-08-15 15:38:08 +02002292 /* skip lyxml_free() at the end of the loop, this node will be processed later */
2293 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02002294
Radek Krejcieb00f512015-07-01 16:44:58 +02002295 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002296 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002297 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002298 goto error;
2299 }
2300
2301 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002302 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002303 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2304 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002305 goto error;
2306 }
2307
2308 GETVAL(value, child, "value");
2309 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002310 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002311 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002312 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002313 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002314 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002315 goto error;
2316 }
2317
2318 if (d->mod == LY_DEVIATE_ADD) {
2319 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01002320 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002321 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2322 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002323 goto error;
2324 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002325
Radek Krejci841ec082016-04-05 13:05:17 +02002326 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02002327 if (d->flags & LYS_MAND_TRUE) {
2328 if (dev_target->nodetype == LYS_CHOICE) {
2329 if (((struct lys_node_choice *)(dev_target))->dflt) {
2330 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2331 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2332 "Adding the \"mandatory\" statement is forbidden on choice with the \"default\" statement.");
2333 goto error;
2334 }
2335 } else if (dev_target->nodetype == LYS_LEAF) {
2336 if (((struct lys_node_leaf *)(dev_target))->dflt) {
2337 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2338 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2339 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
2340 goto error;
2341 }
2342 }
Radek Krejci841ec082016-04-05 13:05:17 +02002343 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002344
Michal Vasko21be1b32016-03-07 12:31:34 +01002345 dev_target->flags |= d->flags & LYS_MAND_MASK;
2346 } else if (d->mod == LY_DEVIATE_RPL) {
2347 /* check that there was a value before */
2348 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002349 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2350 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002351 goto error;
2352 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002353
Michal Vasko21be1b32016-03-07 12:31:34 +01002354 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01002355 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01002356 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002357 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002358 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002359 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002360 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002361
2362 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2363 for (parent = dev_target->parent;
2364 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2365 parent = parent->parent) {
2366 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2367 /* stop also on presence containers */
2368 break;
2369 }
2370 }
2371 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2372 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2373 if (lyp_check_mandatory_choice(parent)) {
2374 goto error;
2375 }
2376 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002377
Radek Krejci8d6b7422017-02-03 14:42:13 +01002378 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002379 goto error;
2380 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002381 } else if (!strcmp(child->name, "min-elements")) {
2382 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002383 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002384 goto error;
2385 }
2386 f_min = 1;
2387
Michal Vasko60f4b452016-02-12 11:02:55 +01002388 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002389 goto error;
2390 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002391 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002392 goto error;
2393 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002394 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002395 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002396 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002397 goto error;
2398 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01002399 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02002400
Michal Vasko60f4b452016-02-12 11:02:55 +01002401 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002402 goto error;
2403 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01002404 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002405 goto error;
2406 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002407 } else if (!strcmp(child->name, "must")) {
2408 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002409 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002410 continue;
2411 } else if (!strcmp(child->name, "type")) {
2412 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002413 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002414 goto error;
2415 }
2416
Michal Vaskof7e57d52016-03-07 11:31:09 +01002417 /* add, del type is forbidden */
2418 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002419 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002420 goto error;
2421 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002422 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002423 goto error;
2424 }
2425
Radek Krejcieb00f512015-07-01 16:44:58 +02002426 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002427 if (dev_target->nodetype == LYS_LEAF) {
2428 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002429 if (((struct lys_node_leaf *)dev_target)->dflt) {
2430 ly_set_add(dflt_check, dev_target, 0);
2431 }
Michal Vasko60f4b452016-02-12 11:02:55 +01002432 } else if (dev_target->nodetype == LYS_LEAFLIST) {
2433 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002434 if (((struct lys_node_leaflist *)dev_target)->dflt) {
2435 ly_set_add(dflt_check, dev_target, 0);
2436 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002437 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002438 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2439 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002440 goto error;
2441 }
2442
Radek Krejcieb00f512015-07-01 16:44:58 +02002443 /* replace */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002444 lys_type_free(ctx, t, NULL);
Michal Vasko88c29542015-11-27 14:57:53 +01002445 /* HACK for unres */
2446 t->der = (struct lys_tpdf *)child;
Michal Vasko3767fb22016-07-21 12:10:57 +02002447 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002448 goto error;
2449 }
2450 d->type = t;
2451 } else if (!strcmp(child->name, "unique")) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01002452 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 +01002453 goto error;
2454 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002455 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002456 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002457 continue;
2458 } else if (!strcmp(child->name, "units")) {
2459 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002460 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002461 goto error;
2462 }
2463
2464 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002465 if (dev_target->nodetype == LYS_LEAFLIST) {
2466 stritem = &((struct lys_node_leaflist *)dev_target)->units;
2467 } else if (dev_target->nodetype == LYS_LEAF) {
2468 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02002469 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002470 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2471 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002472 goto error;
2473 }
2474
2475 /* get units value */
2476 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002477 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02002478
2479 /* apply to target */
2480 if (d->mod == LY_DEVIATE_ADD) {
2481 /* check that there is no current value */
2482 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002483 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2484 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002485 goto error;
2486 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002487
Michal Vasko21be1b32016-03-07 12:31:34 +01002488 *stritem = lydict_insert(ctx, value, 0);
2489 } else if (d->mod == LY_DEVIATE_RPL) {
2490 /* check that there was a value before */
2491 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002492 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2493 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01002494 goto error;
2495 }
2496
2497 lydict_remove(ctx, *stritem);
2498 *stritem = lydict_insert(ctx, value, 0);
2499 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002500 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002501 if (!ly_strequal(*stritem, d->units, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002502 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2503 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002504 goto error;
2505 }
2506 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002507 lydict_remove(ctx, *stritem);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002508 (*stritem) = NULL;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002509
2510 /* remove its extensions */
2511 j = -1;
2512 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_UNITS)) != -1) {
2513 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2514 --j;
2515 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002516 }
2517
Radek Krejci8d6b7422017-02-03 14:42:13 +01002518 if (lyp_yin_parse_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002519 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002520 }
2521 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002522 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002523 goto error;
2524 }
2525
Michal Vasko88c29542015-11-27 14:57:53 +01002526 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002527 }
2528
2529 if (c_must) {
2530 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002531 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002532 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002533 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2534 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002535 break;
Radek Krejci76512572015-08-04 09:47:08 +02002536 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002537 trg_must = &((struct lys_node_container *)dev_target)->must;
2538 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002539 break;
Radek Krejci76512572015-08-04 09:47:08 +02002540 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002541 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2542 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002543 break;
Radek Krejci76512572015-08-04 09:47:08 +02002544 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002545 trg_must = &((struct lys_node_list *)dev_target)->must;
2546 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002547 break;
Radek Krejci76512572015-08-04 09:47:08 +02002548 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002549 case LYS_ANYDATA:
2550 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2551 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002552 break;
2553 default:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002554 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2555 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002556 goto error;
2557 }
2558
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002559 dev_target->flags &= ~LYS_XPATH_DEP;
Michal Vasko508a50d2016-09-07 14:50:33 +02002560
Radek Krejcieb00f512015-07-01 16:44:58 +02002561 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002562 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002563 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002564 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002565 } else if (d->mod == LY_DEVIATE_ADD) {
2566 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002567 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002568 LY_CHECK_ERR_GOTO(!d->must, LOGMEM, error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002569 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02002570 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002571 d->must_size = c_must;
2572 } else { /* LY_DEVIATE_DEL */
2573 d->must = calloc(c_must, sizeof *d->must);
2574 }
Radek Krejcia8d111f2017-05-31 13:57:37 +02002575 LY_CHECK_ERR_GOTO(!d->must, LOGMEM, error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002576 }
2577 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002578 /* replace unique is forbidden */
2579 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002580 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002581 goto error;
2582 }
2583
Radek Krejcieb00f512015-07-01 16:44:58 +02002584 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002585 if (dev_target->nodetype != LYS_LIST) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002586 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2587 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002588 goto error;
2589 }
2590
Michal Vasko60f4b452016-02-12 11:02:55 +01002591 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002592 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002593 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002594 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002595 LY_CHECK_ERR_GOTO(!d->unique, LOGMEM, error);
Radek Krejcieb00f512015-07-01 16:44:58 +02002596 list->unique = d->unique;
2597 d->unique = &list->unique[list->unique_size];
2598 d->unique_size = c_uniq;
2599 } else { /* LY_DEVIATE_DEL */
2600 d->unique = calloc(c_uniq, sizeof *d->unique);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002601 LY_CHECK_ERR_GOTO(!d->unique, LOGMEM, error);
Michal Vasko253035f2015-12-17 16:58:13 +01002602 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002603 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002604 if (c_dflt) {
2605 if (d->mod == LY_DEVIATE_ADD) {
2606 /* check that there is no current value */
2607 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
2608 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
2609 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2610 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
2611 goto error;
2612 }
2613
2614 /* check collision with mandatory/min-elements */
2615 if ((dev_target->flags & LYS_MAND_TRUE) ||
2616 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
2617 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2618 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2619 "Adding the \"default\" statement is forbidden on %s statement.",
2620 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2621 goto error;
2622 }
2623 } else if (d->mod == LY_DEVIATE_RPL) {
2624 /* check that there was a value before */
2625 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2626 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
2627 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2628 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
2629 goto error;
2630 }
2631 }
2632
2633 if (dev_target->nodetype == LYS_LEAFLIST) {
2634 /* reallocate default list in the target */
2635 llist = (struct lys_node_leaflist *)dev_target;
2636 if (d->mod == LY_DEVIATE_ADD) {
2637 /* reallocate (enlarge) the unique array of the target */
2638 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002639 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM, error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002640 } else if (d->mod == LY_DEVIATE_RPL) {
2641 /* reallocate (replace) the unique array of the target */
2642 for (i = 0; i < llist->dflt_size; i++) {
2643 lydict_remove(llist->module->ctx, llist->dflt[i]);
2644 }
2645 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2646 llist->dflt_size = 0;
Radek Krejcia8d111f2017-05-31 13:57:37 +02002647 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM, error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002648 }
2649 }
2650 d->dflt = calloc(c_dflt, sizeof *d->dflt);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002651 LY_CHECK_ERR_GOTO(!d->dflt, LOGMEM, error);
Radek Krejcid5a5c282016-08-15 15:38:08 +02002652 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002653 if (c_ext) {
2654 /* some extensions may be already present from the substatements */
2655 reallocated = realloc(d->ext, (c_ext + d->ext_size) * sizeof *d->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02002656 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002657 d->ext = reallocated;
2658
2659 /* init memory */
2660 memset(&d->ext[d->ext_size], 0, c_ext * sizeof *d->ext);
2661 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002662
2663 /* process deviation properties with 0..n cardinality */
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002664 LY_TREE_FOR_SAFE(develem->child, next2, child) {
2665 if (strcmp(child->ns->value, LY_NSYIN)) {
2666 /* extension */
2667 if (lyp_yin_fill_ext(d, LYEXT_PAR_DEVIATE, 0, 0, module, child, &d->ext, d->ext_size, unres)) {
2668 goto error;
2669 }
2670 d->ext_size++;
2671 } else if (!strcmp(child->name, "must")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002672 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcifccd1442017-01-16 10:26:57 +01002673 if (fill_yin_must(module, child, &d->must[d->must_size], unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002674 goto error;
2675 }
2676
2677 /* find must to delete, we are ok with just matching conditions */
2678 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002679 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002680 /* we have a match, free the must structure ... */
Radek Krejci5138e9f2017-04-12 13:10:46 +02002681 lys_restr_free(ctx, &((*trg_must)[i]), NULL);
Radek Krejcieb00f512015-07-01 16:44:58 +02002682 /* ... and maintain the array */
2683 (*trg_must_size)--;
2684 if (i != *trg_must_size) {
2685 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2686 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2687 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2688 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2689 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2690 }
2691 if (!(*trg_must_size)) {
2692 free(*trg_must);
2693 *trg_must = NULL;
2694 } else {
2695 (*trg_must)[*trg_must_size].expr = NULL;
2696 (*trg_must)[*trg_must_size].dsc = NULL;
2697 (*trg_must)[*trg_must_size].ref = NULL;
2698 (*trg_must)[*trg_must_size].eapptag = NULL;
2699 (*trg_must)[*trg_must_size].emsg = NULL;
2700 }
2701
2702 i = -1; /* set match flag */
2703 break;
2704 }
2705 }
2706 d->must_size++;
2707 if (i != -1) {
2708 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002709 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002710 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01002711 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002712 goto error;
2713 }
2714 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002715 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
Radek Krejcifccd1442017-01-16 10:26:57 +01002716 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]), unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002717 goto error;
2718 }
2719 (*trg_must_size)++;
2720 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002721
2722 /* check XPath dependencies again */
Michal Vaskof96dfb62017-08-17 12:23:49 +02002723 if (*trg_must_size && (unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL) == -1)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02002724 goto error;
2725 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002726 } else if (!strcmp(child->name, "unique")) {
2727 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002728 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002729 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002730 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002731 goto error;
2732 }
2733
2734 /* find unique structures to delete */
2735 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002736 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002737 continue;
2738 }
2739
Radek Krejci581ce772015-11-10 17:22:40 +01002740 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002741 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002742 break;
2743 }
2744 }
2745
Radek Krejci581ce772015-11-10 17:22:40 +01002746 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002747 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002748 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002749 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002750 }
2751 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002752 /* ... and maintain the array */
2753 list->unique_size--;
2754 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002755 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2756 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002757 }
2758
2759 if (!list->unique_size) {
2760 free(list->unique);
2761 list->unique = NULL;
2762 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002763 list->unique[list->unique_size].expr_size = 0;
2764 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002765 }
2766
Radek Krejci6bd2c022017-02-01 15:04:49 +01002767 k = i; /* remember index for removing extensions */
Radek Krejcieb00f512015-07-01 16:44:58 +02002768 i = -1; /* set match flag */
2769 break;
2770 }
2771 }
2772
2773 d->unique_size++;
2774 if (i != -1) {
2775 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002776 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2777 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002778 goto error;
2779 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01002780
2781 /* remove extensions of this unique instance from the target node */
2782 j = -1;
2783 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 +01002784 if (dev_target->ext[j]->insubstmt_index == k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002785 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2786 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01002787 } else if (dev_target->ext[j]->insubstmt_index > k) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002788 /* decrease the substatement index of the extension because of the changed array of uniques */
Radek Krejcifebdad72017-02-06 11:35:51 +01002789 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002790 }
2791 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002792 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002793 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002794 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002795 list->unique_size++;
2796 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002797 goto error;
2798 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002799 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002800 } else if (!strcmp(child->name, "default")) {
2801 GETVAL(value, child, "value");
2802 u = strlen(value);
2803 d->dflt[d->dflt_size++] = lydict_insert(module->ctx, value, u);
2804
2805 if (dev_target->nodetype == LYS_CHOICE) {
2806 choice = (struct lys_node_choice *)dev_target;
2807 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2808 if (rc || !node) {
2809 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2810 goto error;
2811 }
2812 if (d->mod == LY_DEVIATE_DEL) {
2813 if (!choice->dflt || (choice->dflt != node)) {
2814 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2815 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2816 goto error;
2817 }
Radek Krejci6bd2c022017-02-01 15:04:49 +01002818 choice->dflt = NULL;
2819 /* remove extensions of this default instance from the target node */
2820 j = -1;
2821 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
2822 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2823 --j;
2824 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002825 } else { /* add or replace */
2826 choice->dflt = node;
2827 if (!choice->dflt) {
2828 /* default branch not found */
2829 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2830 goto error;
2831 }
2832 }
2833 } else if (dev_target->nodetype == LYS_LEAF) {
2834 leaf = (struct lys_node_leaf *)dev_target;
2835 if (d->mod == LY_DEVIATE_DEL) {
2836 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
2837 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2838 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2839 goto error;
2840 }
2841 /* remove value */
2842 lydict_remove(ctx, leaf->dflt);
2843 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01002844 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002845
2846 /* remove extensions of this default instance from the target node */
2847 j = -1;
2848 while ((j = lys_ext_iter(dev_target->ext, dev_target->ext_size, j + 1, LYEXT_SUBSTMT_DEFAULT)) != -1) {
2849 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2850 --j;
2851 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002852 } else { /* add (already checked) and replace */
2853 /* remove value */
2854 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01002855 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002856
2857 /* set new value */
2858 leaf->dflt = lydict_insert(ctx, value, u);
2859
Radek Krejcibd117f02016-11-04 16:28:08 +01002860 /* remember to check it later (it may not fit now, because the type can be deviated too) */
Radek Krejcid5a5c282016-08-15 15:38:08 +02002861 ly_set_add(dflt_check, dev_target, 0);
2862 }
2863 } else { /* LYS_LEAFLIST */
2864 llist = (struct lys_node_leaflist *)dev_target;
2865 if (d->mod == LY_DEVIATE_DEL) {
2866 /* find and remove the value in target list */
2867 for (i = 0; i < llist->dflt_size; i++) {
2868 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
2869 /* match, remove the value */
2870 lydict_remove(llist->module->ctx, llist->dflt[i]);
2871 llist->dflt[i] = NULL;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002872
2873 /* remove extensions of this default instance from the target node */
2874 j = -1;
2875 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 +01002876 if (dev_target->ext[j]->insubstmt_index == i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002877 lyp_ext_instance_rm(ctx, &dev_target->ext, &dev_target->ext_size, j);
2878 --j;
Radek Krejcifebdad72017-02-06 11:35:51 +01002879 } else if (dev_target->ext[j]->insubstmt_index > i) {
Radek Krejci6bd2c022017-02-01 15:04:49 +01002880 /* decrease the substatement index of the extension because of the changed array of defaults */
Radek Krejcifebdad72017-02-06 11:35:51 +01002881 dev_target->ext[j]->insubstmt_index--;
Radek Krejci6bd2c022017-02-01 15:04:49 +01002882 }
2883 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002884 break;
2885 }
2886 }
2887 if (i == llist->dflt_size) {
2888 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2889 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
2890 goto error;
2891 }
2892 } else {
2893 /* add or replace, anyway we place items into the deviate's list
2894 which propagates to the target */
2895 /* we just want to check that the value isn't already in the list */
2896 for (i = 0; i < llist->dflt_size; i++) {
2897 if (ly_strequal(llist->dflt[i], value, 1)) {
2898 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2899 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2900 goto error;
2901 }
2902 }
2903 /* store it in target node */
2904 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, u);
2905
2906 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2907 ly_set_add(dflt_check, dev_target, 0);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002908 llist->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002909 }
2910 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002911 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002912 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002913
2914 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
2915 /* consolidate the final list in the target after removing items from it */
2916 llist = (struct lys_node_leaflist *)dev_target;
2917 for (i = j = 0; j < llist->dflt_size; j++) {
2918 llist->dflt[i] = llist->dflt[j];
2919 if (llist->dflt[i]) {
2920 i++;
2921 }
2922 }
2923 llist->dflt_size = i + 1;
2924 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002925 }
2926
Michal Vasko43a1feb2016-03-07 12:03:02 +01002927 /* now check whether default value, if any, matches the type */
Pavol Vican85991ec2016-08-16 14:58:12 +02002928 for (u = 0; u < dflt_check->number; ++u) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002929 value = NULL;
2930 rc = EXIT_SUCCESS;
2931 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2932 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
Radek Krejci51673202016-11-01 17:00:32 +01002933 value = leaf->dflt;
2934 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002935 } else { /* LYS_LEAFLIST */
2936 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2937 for (j = 0; j < llist->dflt_size; j++) {
Radek Krejci51673202016-11-01 17:00:32 +01002938 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2939 (struct lys_node *)(&llist->dflt[j]));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002940 if (rc == -1) {
Radek Krejci51673202016-11-01 17:00:32 +01002941 value = llist->dflt[j];
Radek Krejcid5a5c282016-08-15 15:38:08 +02002942 break;
2943 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002944 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002945
2946 }
2947 if (rc == -1) {
2948 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2949 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2950 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2951 dev->target_name);
2952 goto error;
Michal Vasko43a1feb2016-03-07 12:03:02 +01002953 }
2954 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002955
Radek Krejci27fe55e2016-09-13 17:13:35 +02002956 /* mark all the affected modules as deviated and implemented */
2957 for(parent = dev_target; parent; parent = lys_parent(parent)) {
2958 mod = lys_node_module(parent);
2959 if (module != mod) {
Radek Krejci29eac3d2017-06-01 16:50:02 +02002960 mod->deviated = 1; /* main module */
2961 parent->module->deviated = 1; /* possible submodule */
Radek Krejci2bb5be72017-02-27 13:07:25 +01002962 if (lys_set_implemented(mod)) {
2963 LOGERR(ly_errno, "Setting the deviated module \"%s\" implemented failed.", mod->name);
2964 goto error;
2965 }
Radek Krejci27fe55e2016-09-13 17:13:35 +02002966 }
2967 }
2968
Radek Krejcid5a5c282016-08-15 15:38:08 +02002969 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002970 return EXIT_SUCCESS;
2971
2972error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002973 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002974 return EXIT_FAILURE;
2975}
2976
Michal Vasko0d343d12015-08-24 14:57:36 +02002977/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002978static int
Radek Krejcib8048692015-08-05 13:36:34 +02002979fill_yin_augment(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_node_augment *aug,
Radek Krejci7212e0a2017-03-08 15:58:22 +01002980 int options, struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02002981{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002982 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01002983 struct lyxml_elem *sub, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002984 struct lys_node *node;
Radek Krejcie534c132016-11-23 13:32:31 +01002985 int ret, c_ftrs = 0, c_ext = 0;
Radek Krejci30701b42017-01-23 16:41:38 +01002986 void *reallocated;
Radek Krejci106efc02015-06-10 14:36:27 +02002987
Michal Vasko591e0b22015-08-13 13:53:43 +02002988 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002989 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002990 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02002991 if (!aug->target_name) {
2992 goto error;
2993 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002994 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02002995
Radek Krejci07d0fb92017-01-13 14:11:05 +01002996 if (read_yin_common(module, NULL, aug, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002997 goto error;
2998 }
2999
Radek Krejcie534c132016-11-23 13:32:31 +01003000 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3001 if (strcmp(sub->ns->value, LY_NSYIN)) {
3002 /* extension */
3003 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003004 continue;
Radek Krejci30701b42017-01-23 16:41:38 +01003005 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejcie534c132016-11-23 13:32:31 +01003006 c_ftrs++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003007 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003008 } else if (!strcmp(sub->name, "when")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003009 if (aug->when) {
Radek Krejcie534c132016-11-23 13:32:31 +01003010 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003011 goto error;
3012 }
3013
Radek Krejci5323b492017-01-16 15:40:11 +01003014 aug->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003015 if (!aug->when) {
Radek Krejcie534c132016-11-23 13:32:31 +01003016 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003017 goto error;
3018 }
Radek Krejcie534c132016-11-23 13:32:31 +01003019 lyxml_free(module->ctx, sub);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003020 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003021
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003022 /* check allowed data sub-statements */
Radek Krejcie534c132016-11-23 13:32:31 +01003023 } else if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003024 node = read_yin_container(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003025 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003026 node = read_yin_leaflist(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003027 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003028 node = read_yin_leaf(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003029 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003030 node = read_yin_list(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003031 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003032 node = read_yin_uses(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003033 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003034 node = read_yin_choice(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003035 } else if (!strcmp(sub->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003036 node = read_yin_case(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003037 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003038 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYXML, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003039 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003040 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYDATA, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003041 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003042 node = read_yin_rpc_action(module, (struct lys_node *)aug, sub, options, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01003043 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01003044 node = read_yin_notif(module, (struct lys_node *)aug, sub, options, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003045 } else {
Radek Krejcie534c132016-11-23 13:32:31 +01003046 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003047 goto error;
3048 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003049
Radek Krejci1d82ef62015-08-07 14:44:40 +02003050 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003051 goto error;
3052 }
3053
Radek Krejci1d82ef62015-08-07 14:44:40 +02003054 node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01003055 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003056 }
3057
Radek Krejcie534c132016-11-23 13:32:31 +01003058 if (c_ftrs) {
3059 aug->iffeature = calloc(c_ftrs, sizeof *aug->iffeature);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003060 LY_CHECK_ERR_GOTO(!aug->iffeature, LOGMEM, error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003061 }
Radek Krejcie534c132016-11-23 13:32:31 +01003062 if (c_ext) {
Radek Krejci30701b42017-01-23 16:41:38 +01003063 /* some extensions may be already present from the substatements */
3064 reallocated = realloc(aug->ext, (c_ext + aug->ext_size) * sizeof *aug->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003065 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejci30701b42017-01-23 16:41:38 +01003066 aug->ext = reallocated;
3067
3068 /* init memory */
3069 memset(&aug->ext[aug->ext_size], 0, c_ext * sizeof *aug->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003070 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003071
Radek Krejcie534c132016-11-23 13:32:31 +01003072 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3073 if (strcmp(sub->ns->value, LY_NSYIN)) {
3074 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003075 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 +01003076 aug->ext_size++;
3077 if (ret) {
3078 goto error;
3079 }
3080 } else if (!strcmp(sub->name, "if-feature")) {
3081 ret = fill_yin_iffeature((struct lys_node *)aug, 0, sub, &aug->iffeature[aug->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003082 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003083 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003084 goto error;
3085 }
Radek Krejcie534c132016-11-23 13:32:31 +01003086 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003087 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003088 }
3089
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003090 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02003091 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02003092 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02003093 * when the uses does and cannot be resolved now for sure
3094 * (the grouping was not yet copied into uses).
3095 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02003096 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003097 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02003098 goto error;
3099 }
Michal Vasko49291b32015-08-06 09:49:41 +02003100 }
Radek Krejci106efc02015-06-10 14:36:27 +02003101
Michal Vasko508a50d2016-09-07 14:50:33 +02003102 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01003103 if (aug->when) {
3104 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01003105 if (lyxp_node_check_syntax((struct lys_node *)aug)) {
Michal Vasko89afc112017-03-16 13:57:28 +01003106 goto error;
3107 }
3108 } else {
3109 if (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1) {
3110 goto error;
3111 }
3112 }
Michal Vasko508a50d2016-09-07 14:50:33 +02003113 }
3114
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003115 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02003116
3117error:
3118
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003119 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02003120}
3121
Michal Vasko0d343d12015-08-24 14:57:36 +02003122/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003123static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02003124fill_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 +02003125{
Radek Krejci363bd4a2016-07-29 14:30:20 +02003126 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003127 struct lyxml_elem *sub, *next;
3128 const char *value;
3129 char *endptr;
3130 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01003131 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003132 int r;
3133 unsigned long int val;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003134 void *reallocated;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003135
Radek Krejci363bd4a2016-07-29 14:30:20 +02003136 assert(uses);
3137 module = uses->module; /* shorthand */
3138
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003139 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003140 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02003141 if (!rfn->target_name) {
3142 goto error;
3143 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003145 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003146 if (!sub->ns) {
3147 /* garbage */
3148 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01003149 /* extension */
3150 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003151 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02003152
Radek Krejci411b1bf2017-01-23 16:40:05 +01003153 } else if (!strcmp(sub->name, "description")) {
3154 if (rfn->dsc) {
3155 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3156 goto error;
3157 }
3158
Radek Krejci8d6b7422017-02-03 14:42:13 +01003159 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003160 goto error;
3161 }
3162
3163 rfn->dsc = read_yin_subnode(module->ctx, sub, "text");
3164 if (!rfn->dsc) {
3165 goto error;
3166 }
3167 } else if (!strcmp(sub->name, "reference")) {
3168 if (rfn->ref) {
3169 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3170 goto error;
3171 }
3172
Radek Krejci8d6b7422017-02-03 14:42:13 +01003173 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003174 goto error;
3175 }
3176
3177 rfn->ref = read_yin_subnode(module->ctx, sub, "text");
3178 if (!rfn->ref) {
3179 goto error;
3180 }
3181 } else if (!strcmp(sub->name, "config")) {
3182 if (rfn->flags & LYS_CONFIG_MASK) {
3183 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3184 goto error;
3185 }
3186 GETVAL(value, sub, "value");
3187 if (!strcmp(value, "false")) {
3188 rfn->flags |= LYS_CONFIG_R;
3189 } else if (!strcmp(value, "true")) {
3190 rfn->flags |= LYS_CONFIG_W;
3191 } else {
3192 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3193 goto error;
3194 }
3195 rfn->flags |= LYS_CONFIG_SET;
3196
Radek Krejci8d6b7422017-02-03 14:42:13 +01003197 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003198 goto error;
3199 }
Radek Krejcie534c132016-11-23 13:32:31 +01003200 } else if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02003201 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02003202
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003203 /* check possibility of statements combination */
3204 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02003205 if (c_dflt) {
3206 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003207 if (module->version < 2) {
3208 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3209 goto error;
3210 }
Radek Krejci200bf712016-08-16 17:11:04 +02003211 rfn->target_type &= LYS_LEAFLIST;
3212 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003213 if (module->version < 2) {
3214 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
3215 } else {
3216 /* YANG 1.1 */
3217 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
3218 }
Radek Krejci200bf712016-08-16 17:11:04 +02003219 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003220 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003221 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3222 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003223 goto error;
3224 }
3225 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003226 if (module->version < 2) {
3227 rfn->target_type = LYS_LEAF | LYS_CHOICE;
3228 } else {
3229 /* YANG 1.1 */
3230 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
3231 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003232 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003233
Radek Krejci8d6b7422017-02-03 14:42:13 +01003234 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 +01003235 goto error;
3236 }
Radek Krejci200bf712016-08-16 17:11:04 +02003237 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003238 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003239 } else if (!strcmp(sub->name, "mandatory")) {
3240 /* leaf, choice or anyxml */
3241 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003242 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003243 goto error;
3244 }
3245 /* just checking the flags in leaf is not sufficient, we would allow
3246 * multiple mandatory statements with the "false" value
3247 */
3248 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003249
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003250 /* check possibility of statements combination */
3251 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003252 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003253 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003254 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3255 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003256 goto error;
3257 }
3258 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003259 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003260 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003261
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003262 GETVAL(value, sub, "value");
3263 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003264 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003265 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003266 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003267 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003268 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003269 goto error;
3270 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003271 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003272 goto error;
3273 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003274 } else if (!strcmp(sub->name, "min-elements")) {
3275 /* list or leaf-list */
3276 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003277 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003278 goto error;
3279 }
3280 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003281
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003282 /* check possibility of statements combination */
3283 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003284 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003285 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003286 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3287 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003288 goto error;
3289 }
3290 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003291 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003292 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003293
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003294 GETVAL(value, sub, "value");
3295 while (isspace(value[0])) {
3296 value++;
3297 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003298
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003299 /* convert it to uint32_t */
3300 errno = 0;
3301 endptr = NULL;
3302 val = strtoul(value, &endptr, 10);
3303 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003304 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003305 goto error;
3306 }
3307 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003308 rfn->flags |= LYS_RFN_MINSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003309
Radek Krejci8d6b7422017-02-03 14:42:13 +01003310 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003311 goto error;
3312 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003313 } else if (!strcmp(sub->name, "max-elements")) {
3314 /* list or leaf-list */
3315 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003316 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003317 goto error;
3318 }
3319 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003320
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003321 /* check possibility of statements combination */
3322 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003323 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003324 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003325 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3326 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003327 goto error;
3328 }
3329 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003330 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003331 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003332
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003333 GETVAL(value, sub, "value");
3334 while (isspace(value[0])) {
3335 value++;
3336 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003337
Radek Krejci0d7b2472016-02-12 11:11:03 +01003338 if (!strcmp(value, "unbounded")) {
3339 rfn->mod.list.max = 0;
3340 } else {
3341 /* convert it to uint32_t */
3342 errno = 0;
3343 endptr = NULL;
3344 val = strtoul(value, &endptr, 10);
3345 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003346 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003347 goto error;
3348 }
3349 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003350 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003351 rfn->flags |= LYS_RFN_MAXSET;
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_MAX, 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, "presence")) {
3357 /* container */
3358 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003359 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003360 goto error;
3361 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003362
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003363 /* check possibility of statements combination */
3364 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003365 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003366 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003367 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3368 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003369 goto error;
3370 }
3371 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003372 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003373 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003374
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003375 GETVAL(value, sub, "value");
3376 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcifdc0d702017-01-23 15:58:38 +01003377
Radek Krejci8d6b7422017-02-03 14:42:13 +01003378 if (lyp_yin_parse_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003379 goto error;
3380 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003381 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02003382 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003383 /* check possibility of statements combination */
3384 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003385 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003386 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003387 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3388 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003389 goto error;
3390 }
3391 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003392 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003393 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003395 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003396 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003397
Radek Krejci363bd4a2016-07-29 14:30:20 +02003398 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
3399 /* leaf, leaf-list, list, container or anyxml */
3400 /* check possibility of statements combination */
3401 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003402 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003403 if (!rfn->target_type) {
3404 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3405 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
3406 goto error;
3407 }
3408 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003409 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003410 }
3411
3412 c_ftrs++;
3413 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003414 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003415 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003416 goto error;
3417 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003418
Michal Vasko345da0a2015-12-02 10:35:55 +01003419 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003420 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003421
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003422 /* process nodes with cardinality of 0..n */
3423 if (c_must) {
3424 rfn->must = calloc(c_must, sizeof *rfn->must);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003425 LY_CHECK_ERR_GOTO(!rfn->must, LOGMEM, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003426 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02003427 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02003428 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003429 LY_CHECK_ERR_GOTO(!rfn->iffeature, LOGMEM, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003430 }
Radek Krejci200bf712016-08-16 17:11:04 +02003431 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003432 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003433 LY_CHECK_ERR_GOTO(!rfn->dflt, LOGMEM, error);
Radek Krejci200bf712016-08-16 17:11:04 +02003434 }
Radek Krejcie534c132016-11-23 13:32:31 +01003435 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003436 /* some extensions may be already present from the substatements */
3437 reallocated = realloc(rfn->ext, (c_ext + rfn->ext_size) * sizeof *rfn->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003438 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01003439 rfn->ext = reallocated;
3440
3441 /* init memory */
3442 memset(&rfn->ext[rfn->ext_size], 0, c_ext * sizeof *rfn->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003443 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003444
Radek Krejcie534c132016-11-23 13:32:31 +01003445 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3446 if (strcmp(sub->ns->value, LY_NSYIN)) {
3447 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003448 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 +01003449 rfn->ext_size++;
3450 if (r) {
3451 goto error;
3452 }
3453 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003454 r = fill_yin_iffeature(uses, 0, sub, &rfn->iffeature[rfn->iffeature_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003455 rfn->iffeature_size++;
3456 if (r) {
3457 goto error;
3458 }
Radek Krejci200bf712016-08-16 17:11:04 +02003459 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01003460 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003461 rfn->must_size++;
3462 if (r) {
3463 goto error;
3464 }
Radek Krejci200bf712016-08-16 17:11:04 +02003465 } else { /* default */
3466 GETVAL(value, sub, "value");
3467
3468 /* check for duplicity */
3469 for (r = 0; r < rfn->dflt_size; r++) {
3470 if (ly_strequal(rfn->dflt[r], value, 1)) {
3471 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3472 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
3473 goto error;
3474 }
3475 }
3476 rfn->dflt[rfn->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02003477 }
3478 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003479
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003480 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003481
3482error:
3483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003484 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003485}
3486
Michal Vasko0d343d12015-08-24 14:57:36 +02003487/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003488static int
Radek Krejcie534c132016-11-23 13:32:31 +01003489fill_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 +02003490{
Radek Krejcie534c132016-11-23 13:32:31 +01003491 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003492 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003493 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003494 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003495
Radek Krejcie534c132016-11-23 13:32:31 +01003496 /* init */
3497 memset(&exts, 0, sizeof exts);
3498
3499 LY_TREE_FOR_SAFE(yin->child, next, child) {
3500 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003501 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003502 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003503 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3504 /* extension */
3505 c_ext++;
3506 lyxml_unlink_elem(module->ctx, child, 2);
3507 lyxml_add_child(module->ctx, &exts, child);
3508 } else if (!strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003509 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01003510 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003511 goto error;
3512 }
3513 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01003514
Radek Krejci8d6b7422017-02-03 14:42:13 +01003515 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003516 goto error;
3517 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003518 } else if (!strcmp(child->name, "revision-date")) {
3519 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02003520 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3521 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003522 }
3523 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003524 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003525 goto error;
3526 }
3527 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003528
Radek Krejci8d6b7422017-02-03 14:42:13 +01003529 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003530 goto error;
3531 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003532 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003533 if (imp->dsc) {
3534 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3535 goto error;
3536 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003537 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003538 goto error;
3539 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003540 imp->dsc = read_yin_subnode(module->ctx, child, "text");
3541 if (!imp->dsc) {
3542 goto error;
3543 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003544 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003545 if (imp->ref) {
3546 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3547 goto error;
3548 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003549 if (lyp_yin_parse_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003550 goto error;
3551 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003552 imp->ref = read_yin_subnode(module->ctx, child, "text");
3553 if (!imp->ref) {
3554 goto error;
3555 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003556 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003557 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003558 goto error;
3559 }
3560 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003561
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003562 /* check mandatory information */
3563 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003564 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003565 goto error;
3566 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003567
Radek Krejcie534c132016-11-23 13:32:31 +01003568 /* process extensions */
3569 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003570 /* some extensions may be already present from the substatements */
3571 reallocated = realloc(imp->ext, (c_ext + imp->ext_size) * sizeof *imp->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003572 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003573 imp->ext = reallocated;
3574
3575 /* init memory */
3576 memset(&imp->ext[imp->ext_size], 0, c_ext * sizeof *imp->ext);
3577
Radek Krejcie534c132016-11-23 13:32:31 +01003578 LY_TREE_FOR_SAFE(exts.child, next, child) {
3579 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003580 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 +01003581 imp->ext_size++;
3582 if (r) {
3583 goto error;
3584 }
3585 }
3586 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003587
Radek Krejcie534c132016-11-23 13:32:31 +01003588 GETVAL(value, yin, "module");
Pavol Vicane994fda2016-03-22 10:47:58 +01003589 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02003590
3591error:
3592
Radek Krejcie534c132016-11-23 13:32:31 +01003593 while (exts.child) {
3594 lyxml_free(module->ctx, exts.child);
3595 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003596 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02003597}
3598
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003599/* logs directly
3600 * returns:
3601 * 0 - inc successfully filled
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003602 * -1 - error
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003603 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003604static int
Michal Vasko5ff78822016-02-12 09:33:31 +01003605fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
3606 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02003607{
Radek Krejcie534c132016-11-23 13:32:31 +01003608 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003609 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003610 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003611 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003612
Radek Krejcie534c132016-11-23 13:32:31 +01003613 /* init */
3614 memset(&exts, 0, sizeof exts);
3615
3616 LY_TREE_FOR_SAFE(yin->child, next, child) {
3617 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003618 /* garbage */
3619 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003620 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3621 /* extension */
3622 c_ext++;
3623 lyxml_unlink_elem(module->ctx, child, 2);
3624 lyxml_add_child(module->ctx, &exts, child);
3625 } else if (!strcmp(child->name, "revision-date")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003626 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003627 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003628 goto error;
3629 }
3630 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003631 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003632 goto error;
3633 }
3634 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003635
Radek Krejci8d6b7422017-02-03 14:42:13 +01003636 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003637 goto error;
3638 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003639 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003640 if (inc->dsc) {
3641 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3642 goto error;
3643 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003644 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003645 goto error;
3646 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003647 inc->dsc = read_yin_subnode(module->ctx, child, "text");
3648 if (!inc->dsc) {
3649 goto error;
3650 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003651 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003652 if (inc->ref) {
3653 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3654 goto error;
3655 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01003656 if (lyp_yin_parse_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003657 goto error;
3658 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003659 inc->ref = read_yin_subnode(module->ctx, child, "text");
3660 if (!inc->ref) {
3661 goto error;
3662 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003663 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003664 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003665 goto error;
3666 }
3667 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003668
Radek Krejcie534c132016-11-23 13:32:31 +01003669 /* process extensions */
3670 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003671 /* some extensions may be already present from the substatements */
3672 reallocated = realloc(inc->ext, (c_ext + inc->ext_size) * sizeof *inc->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003673 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003674 inc->ext = reallocated;
3675
3676 /* init memory */
3677 memset(&inc->ext[inc->ext_size], 0, c_ext * sizeof *inc->ext);
3678
Radek Krejcie534c132016-11-23 13:32:31 +01003679 LY_TREE_FOR_SAFE(exts.child, next, child) {
3680 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003681 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 +01003682 inc->ext_size++;
3683 if (r) {
3684 goto error;
3685 }
3686 }
3687 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003688
Radek Krejcie534c132016-11-23 13:32:31 +01003689 GETVAL(value, yin, "module");
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003690 return lyp_check_include(submodule ? (struct lys_module *)submodule : module, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02003691
3692error:
3693
Radek Krejci83e3f5b2016-06-24 14:55:25 +02003694 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02003695}
3696
Michal Vasko0d343d12015-08-24 14:57:36 +02003697/* logs directly
3698 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003699 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02003700 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02003701 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003702 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003703static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01003704read_yin_common(struct lys_module *module, struct lys_node *parent, void *stmt, LYEXT_PAR stmt_type,
3705 struct lyxml_elem *xmlnode, int opt, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003706{
Radek Krejci07d0fb92017-01-13 14:11:05 +01003707 struct lys_node *node = stmt;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003708 const char *value;
3709 struct lyxml_elem *sub, *next;
3710 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003711
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003712 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003713 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003714 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003715
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003716 if (opt & OPT_IDENT) {
3717 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01003718 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003719 goto error;
3720 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003721 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003722 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003723
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003724 /* process local parameters */
3725 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003726 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003727 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003728 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02003729 continue;
3730 }
3731 if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejci6ff885d2017-01-03 14:06:22 +01003732 /* possibly an extension, keep the node for later processing, so skipping lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003733 continue;
3734 }
3735
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003736 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003737 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003738 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003739 goto error;
3740 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003741
Radek Krejci8d6b7422017-02-03 14:42:13 +01003742 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003743 goto error;
3744 }
3745
Radek Krejci1d82ef62015-08-07 14:44:40 +02003746 node->dsc = read_yin_subnode(ctx, sub, "text");
3747 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003748 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003749 }
3750 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003751 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003752 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003753 goto error;
3754 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003755
Radek Krejci8d6b7422017-02-03 14:42:13 +01003756 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003757 goto error;
3758 }
3759
Radek Krejci1d82ef62015-08-07 14:44:40 +02003760 node->ref = read_yin_subnode(ctx, sub, "text");
3761 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003762 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003763 }
3764 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003765 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003766 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003767 goto error;
3768 }
3769 GETVAL(value, sub, "value");
3770 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003771 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003772 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003773 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003774 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003775 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003776 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003777 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003778 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003779 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003780
Radek Krejci8d6b7422017-02-03 14:42:13 +01003781 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_STATUS, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003782 goto error;
3783 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003784 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3785 if (opt & OPT_CFG_PARSE) {
3786 if (node->flags & LYS_CONFIG_MASK) {
3787 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
3788 goto error;
3789 }
3790 GETVAL(value, sub, "value");
3791 if (!strcmp(value, "false")) {
3792 node->flags |= LYS_CONFIG_R;
3793 } else if (!strcmp(value, "true")) {
3794 node->flags |= LYS_CONFIG_W;
3795 } else {
3796 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3797 goto error;
3798 }
3799 node->flags |= LYS_CONFIG_SET;
Radek Krejci07d0fb92017-01-13 14:11:05 +01003800
Radek Krejci8d6b7422017-02-03 14:42:13 +01003801 if (lyp_yin_parse_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003802 goto error;
3803 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003804 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003805 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003806 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003807 continue;
3808 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003809 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003810 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003811
Michal Vaskoe022a562016-09-27 14:24:15 +02003812 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003813 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02003814 if (parent) {
3815 node->flags |= parent->flags & LYS_CONFIG_MASK;
3816 } else if (!parent) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003817 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003818 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003819 }
3820 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003821
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003822 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02003823
3824error:
3825
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003826 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003827}
3828
Michal Vasko0d343d12015-08-24 14:57:36 +02003829/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003830static struct lys_when *
Radek Krejci5323b492017-01-16 15:40:11 +01003831read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003832{
Radek Krejci76512572015-08-04 09:47:08 +02003833 struct lys_when *retval = NULL;
Radek Krejci5323b492017-01-16 15:40:11 +01003834 struct lyxml_elem *child, *next;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003835 const char *value;
3836
3837 retval = calloc(1, sizeof *retval);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003838 LY_CHECK_ERR_RETURN(!retval, LOGMEM, NULL);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003839
3840 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01003841 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02003842 if (!retval->cond) {
3843 goto error;
3844 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003845
Radek Krejci5323b492017-01-16 15:40:11 +01003846 LY_TREE_FOR_SAFE(yin->child, next, child) {
3847 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003848 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003849 continue;
Radek Krejci5323b492017-01-16 15:40:11 +01003850 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3851 /* extensions */
Radek Krejci8d6b7422017-02-03 14:42:13 +01003852 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003853 goto error;
3854 }
3855 } else if (!strcmp(child->name, "description")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003856 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003857 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003858 goto error;
3859 }
Radek Krejci5323b492017-01-16 15:40:11 +01003860
Radek Krejci8d6b7422017-02-03 14:42:13 +01003861 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003862 goto error;
3863 }
3864
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003865 retval->dsc = read_yin_subnode(module->ctx, child, "text");
3866 if (!retval->dsc) {
3867 goto error;
3868 }
3869 } else if (!strcmp(child->name, "reference")) {
3870 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003871 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003872 goto error;
3873 }
Radek Krejci5323b492017-01-16 15:40:11 +01003874
Radek Krejci8d6b7422017-02-03 14:42:13 +01003875 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003876 goto error;
3877 }
3878
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003879 retval->ref = read_yin_subnode(module->ctx, child, "text");
3880 if (!retval->ref) {
3881 goto error;
3882 }
3883 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003884 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003885 goto error;
3886 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003887 }
3888
3889 return retval;
3890
3891error:
3892
Radek Krejci5138e9f2017-04-12 13:10:46 +02003893 lys_when_free(module->ctx, retval, NULL);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003894 return NULL;
3895}
3896
Michal Vasko0d343d12015-08-24 14:57:36 +02003897/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003898static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01003899read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02003900 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02003901{
Michal Vasko29fc0182015-08-24 15:02:39 +02003902 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003903 struct lys_node_case *cs;
3904 struct lys_node *retval, *node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01003905 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01003906 void *reallocated;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003907
Radek Krejcie867c852015-08-27 09:52:34 +02003908 /* init */
3909 memset(&root, 0, sizeof root);
3910
Radek Krejci1d82ef62015-08-07 14:44:40 +02003911 cs = calloc(1, sizeof *cs);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003912 LY_CHECK_ERR_RETURN(!cs, LOGMEM, NULL);
Radek Krejci1d82ef62015-08-07 14:44:40 +02003913 cs->nodetype = LYS_CASE;
3914 cs->prev = (struct lys_node *)cs;
3915 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003916
Radek Krejci07d0fb92017-01-13 14:11:05 +01003917 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01003918 OPT_IDENT | OPT_MODULE | (!(options & LYS_PARSE_OPT_CFG_MASK) ? OPT_CFG_INHERIT : 0), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003919 goto error;
3920 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003921
Michal Vasko3e3228d2017-02-24 14:55:32 +01003922 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02003923
Michal Vasko3a0043f2015-08-12 12:11:30 +02003924 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003925 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003926 goto error;
3927 }
3928
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003929 /* process choice's specific children */
3930 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01003931 if (strcmp(sub->ns->value, LY_NSYIN)) {
3932 /* extension */
3933 c_ext++;
3934 } else if (!strcmp(sub->name, "container") ||
Michal Vasko29fc0182015-08-24 15:02:39 +02003935 !strcmp(sub->name, "leaf-list") ||
3936 !strcmp(sub->name, "leaf") ||
3937 !strcmp(sub->name, "list") ||
3938 !strcmp(sub->name, "uses") ||
3939 !strcmp(sub->name, "choice") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01003940 !strcmp(sub->name, "anyxml") ||
3941 !strcmp(sub->name, "anydata")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02003942
Michal Vaskof3930de2015-10-22 12:03:59 +02003943 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02003944 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003945 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02003946 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003947 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003948 if (cs->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003949 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003950 goto error;
3951 }
3952
Radek Krejci5323b492017-01-16 15:40:11 +01003953 cs->when = read_yin_when(module, sub, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02003954 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003955 goto error;
3956 }
Michal Vasko29fc0182015-08-24 15:02:39 +02003957
Michal Vasko345da0a2015-12-02 10:35:55 +01003958 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003959 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003960 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003961 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003962 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003963 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003964
Radek Krejci3cf9e222015-06-18 11:37:50 +02003965 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003966 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003967 LY_CHECK_ERR_GOTO(!cs->iffeature, LOGMEM, error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003968 }
Radek Krejcie534c132016-11-23 13:32:31 +01003969 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01003970 /* some extensions may be already present from the substatements */
3971 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02003972 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejci21c81652017-01-23 10:42:55 +01003973 retval->ext = reallocated;
3974
3975 /* init memory */
3976 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003977 }
Radek Krejci21c81652017-01-23 10:42:55 +01003978
Radek Krejcie534c132016-11-23 13:32:31 +01003979 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3980 if (strcmp(sub->ns->value, LY_NSYIN)) {
3981 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003982 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 +01003983 retval->ext_size++;
3984 if (ret) {
3985 goto error;
3986 }
3987 } else {
3988 /* if-feature */
3989 ret = fill_yin_iffeature(retval, 0, sub, &cs->iffeature[cs->iffeature_size], unres);
3990 cs->iffeature_size++;
3991 if (ret) {
3992 goto error;
3993 }
3994 }
3995 }
Radek Krejcib388c152015-06-04 17:03:03 +02003996
Michal Vasko29fc0182015-08-24 15:02:39 +02003997 /* last part - process data nodes */
3998 LY_TREE_FOR_SAFE(root.child, next, sub) {
3999 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004000 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004001 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004002 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004003 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004004 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004005 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004006 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004007 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004008 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004009 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004010 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004011 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004012 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02004013 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004014 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02004015 }
4016 if (!node) {
4017 goto error;
4018 }
4019
Michal Vasko345da0a2015-12-02 10:35:55 +01004020 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02004021 }
4022
Michal Vasko508a50d2016-09-07 14:50:33 +02004023 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01004024 if (cs->when) {
4025 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004026 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004027 goto error;
4028 }
4029 } else {
4030 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4031 goto error;
4032 }
4033 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004034 }
4035
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004036 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004037
4038error:
4039
Michal Vasko29fc0182015-08-24 15:02:39 +02004040 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004041 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02004042 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004043 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02004044
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004045 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004046}
4047
Michal Vasko0d343d12015-08-24 14:57:36 +02004048/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004049static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004050read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskoe022a562016-09-27 14:24:15 +02004051 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004052{
Radek Krejci629cdef2016-06-06 15:06:36 +02004053 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004054 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004055 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02004056 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02004057 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01004058 int f_mand = 0, c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004059 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004060
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004061 choice = calloc(1, sizeof *choice);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004062 LY_CHECK_ERR_RETURN(!choice, LOGMEM, NULL);
4063
Radek Krejci76512572015-08-04 09:47:08 +02004064 choice->nodetype = LYS_CHOICE;
4065 choice->prev = (struct lys_node *)choice;
4066 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004067
Radek Krejci07d0fb92017-01-13 14:11:05 +01004068 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004069 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4070 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4071 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004072 goto error;
4073 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004074
Michal Vasko3e3228d2017-02-24 14:55:32 +01004075 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02004076
Michal Vasko3a0043f2015-08-12 12:11:30 +02004077 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004078 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004079 goto error;
4080 }
4081
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004082 /* process choice's specific children */
4083 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004084 if (strcmp(sub->ns->value, LY_NSYIN)) {
4085 /* extension */
4086 c_ext++;
4087 /* keep it for later processing, skip lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02004088 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004089 } else if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004090 if (!(node = read_yin_container(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004091 goto error;
4092 }
4093 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004094 if (!(node = read_yin_leaflist(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004095 goto error;
4096 }
4097 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004098 if (!(node = read_yin_leaf(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004099 goto error;
4100 }
4101 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004102 if (!(node = read_yin_list(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004103 goto error;
4104 }
4105 } else if (!strcmp(sub->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004106 if (!(node = read_yin_case(module, retval, sub, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004107 goto error;
4108 }
4109 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004110 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004111 goto error;
4112 }
4113 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004114 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004115 goto error;
4116 }
4117 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02004118 if (dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004119 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004120 goto error;
4121 }
Radek Krejci21c81652017-01-23 10:42:55 +01004122
Radek Krejci8d6b7422017-02-03 14:42:13 +01004123 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004124 goto error;
4125 }
4126
Radek Krejci629cdef2016-06-06 15:06:36 +02004127 dflt = sub;
4128 lyxml_unlink_elem(ctx, dflt, 0);
Radek Krejcif9a312c2016-06-06 15:14:30 +02004129 continue;
4130 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
4131
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004132 } else if (!strcmp(sub->name, "mandatory")) {
4133 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004134 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004135 goto error;
4136 }
4137 /* just checking the flags in leaf is not sufficient, we would allow
4138 * multiple mandatory statements with the "false" value
4139 */
4140 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004141
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004142 GETVAL(value, sub, "value");
4143 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004144 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004145 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004146 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004147 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004148 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004149 goto error;
4150 } /* else false is the default value, so we can ignore it */
Radek Krejci21c81652017-01-23 10:42:55 +01004151
Radek Krejci8d6b7422017-02-03 14:42:13 +01004152 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci21c81652017-01-23 10:42:55 +01004153 goto error;
4154 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004155 } else if (!strcmp(sub->name, "when")) {
4156 if (choice->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004157 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004158 goto error;
4159 }
4160
Radek Krejci5323b492017-01-16 15:40:11 +01004161 choice->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004162 if (!choice->when) {
4163 goto error;
4164 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004165 } else if (!strcmp(sub->name, "if-feature")) {
4166 c_ftrs++;
4167
Michal Vasko345da0a2015-12-02 10:35:55 +01004168 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02004169 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02004170 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01004171 if (!(node = read_yin_choice(module, retval, sub, options, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02004172 goto error;
4173 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004174 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004175 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004176 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004177 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004178
Radek Krejci1d82ef62015-08-07 14:44:40 +02004179 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01004180 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004181 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004182
Radek Krejci3cf9e222015-06-18 11:37:50 +02004183 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004184 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004185 LY_CHECK_ERR_GOTO(!choice->iffeature, LOGMEM, error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004186 }
Radek Krejcie534c132016-11-23 13:32:31 +01004187 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004188 /* some extensions may be already present from the substatements */
4189 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004190 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejci21c81652017-01-23 10:42:55 +01004191 retval->ext = reallocated;
4192
4193 /* init memory */
4194 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004195 }
4196
Radek Krejcie534c132016-11-23 13:32:31 +01004197 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4198 if (strcmp(sub->ns->value, LY_NSYIN)) {
4199 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004200 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 +01004201 retval->ext_size++;
4202 if (ret) {
4203 goto error;
4204 }
4205 } else {
4206 ret = fill_yin_iffeature(retval, 0, sub, &choice->iffeature[choice->iffeature_size], unres);
4207 choice->iffeature_size++;
4208 if (ret) {
4209 goto error;
4210 }
4211 }
4212 }
4213
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004214 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02004215 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004216 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "default", "choice");
Michal Vasko51e5c582017-01-19 14:16:39 +01004217 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004218 goto error;
4219 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004220
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004221 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02004222 if (dflt) {
4223 GETVAL(value, dflt, "value");
4224 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004225 goto error;
4226 }
Radek Krejci629cdef2016-06-06 15:06:36 +02004227 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004228 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004229
Michal Vasko508a50d2016-09-07 14:50:33 +02004230 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01004231 if (choice->when) {
4232 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004233 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004234 goto error;
4235 }
4236 } else {
4237 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4238 goto error;
4239 }
4240 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004241 }
4242
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004243 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004244
4245error:
4246
Radek Krejci629cdef2016-06-06 15:06:36 +02004247 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004248 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004249
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004250 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004251}
4252
Michal Vasko0d343d12015-08-24 14:57:36 +02004253/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004254static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004255read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004256 int options, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02004257{
Radek Krejci76512572015-08-04 09:47:08 +02004258 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02004259 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004260 struct lyxml_elem *sub, *next;
4261 const char *value;
4262 int r;
4263 int f_mand = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004264 int c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004265 void *reallocated;
Radek Krejci863c2852015-06-03 15:47:11 +02004266
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004267 anyxml = calloc(1, sizeof *anyxml);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004268 LY_CHECK_ERR_RETURN(!anyxml, LOGMEM, NULL);
4269
Radek Krejcibf2abff2016-08-23 15:51:52 +02004270 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02004271 anyxml->prev = (struct lys_node *)anyxml;
4272 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02004273
Radek Krejci07d0fb92017-01-13 14:11:05 +01004274 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004275 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4276 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4277 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004278 goto error;
4279 }
Radek Krejci863c2852015-06-03 15:47:11 +02004280
Michal Vasko3e3228d2017-02-24 14:55:32 +01004281 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004282
Radek Krejcic189a952016-07-11 15:27:07 +02004283 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004284 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004285 goto error;
4286 }
4287
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004288 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004289 if (strcmp(sub->ns->value, LY_NSYIN)) {
4290 /* extension */
4291 c_ext++;
4292 } else if (!strcmp(sub->name, "mandatory")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004293 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004294 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004295 goto error;
4296 }
4297 /* just checking the flags in leaf is not sufficient, we would allow
4298 * multiple mandatory statements with the "false" value
4299 */
4300 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02004301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004302 GETVAL(value, sub, "value");
4303 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004304 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004305 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004306 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004307 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004308 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004309 goto error;
4310 }
4311 /* else false is the default value, so we can ignore it */
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004312
Radek Krejci8d6b7422017-02-03 14:42:13 +01004313 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004314 goto error;
4315 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004316 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004317 } else if (!strcmp(sub->name, "when")) {
4318 if (anyxml->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004319 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004320 goto error;
4321 }
4322
Radek Krejci5323b492017-01-16 15:40:11 +01004323 anyxml->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004324 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004325 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004326 goto error;
4327 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004328 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004329 } else if (!strcmp(sub->name, "must")) {
4330 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004331 } else if (!strcmp(sub->name, "if-feature")) {
4332 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02004333
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004334 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004335 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004336 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004337 }
4338 }
Radek Krejci863c2852015-06-03 15:47:11 +02004339
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004340 /* middle part - process nodes with cardinality of 0..n */
4341 if (c_must) {
4342 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004343 LY_CHECK_ERR_GOTO(!anyxml->must, LOGMEM, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004344 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004345 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004346 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004347 LY_CHECK_ERR_GOTO(!anyxml->iffeature, LOGMEM, error);
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);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004352 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004353 retval->ext = reallocated;
4354
4355 /* init memory */
4356 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004357 }
Radek Krejci863c2852015-06-03 15:47:11 +02004358
Radek Krejcie534c132016-11-23 13:32:31 +01004359 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4360 if (strcmp(sub->ns->value, LY_NSYIN)) {
4361 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004362 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 +01004363 retval->ext_size++;
4364 if (r) {
4365 goto error;
4366 }
4367 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004368 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004369 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004370 if (r) {
4371 goto error;
4372 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004373 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004374 r = fill_yin_iffeature(retval, 0, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004375 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004376 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004377 goto error;
4378 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004379 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004380 }
Radek Krejci863c2852015-06-03 15:47:11 +02004381
Michal Vasko508a50d2016-09-07 14:50:33 +02004382 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01004383 if (anyxml->when || anyxml->must) {
4384 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004385 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004386 goto error;
4387 }
4388 } else {
4389 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4390 goto error;
4391 }
4392 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004393 }
4394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004395 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02004396
4397error:
4398
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004399 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02004400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004401 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02004402}
4403
Michal Vasko0d343d12015-08-24 14:57:36 +02004404/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004405static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004406read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004407 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004408{
Radek Krejci76512572015-08-04 09:47:08 +02004409 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004410 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004411 struct lyxml_elem *sub, *next;
4412 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01004413 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004414 int c_must = 0, c_ftrs = 0, f_mand = 0, c_ext = 0;
Radek Krejcifccd1442017-01-16 10:26:57 +01004415 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004416
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004417 leaf = calloc(1, sizeof *leaf);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004418 LY_CHECK_ERR_RETURN(!leaf, LOGMEM, NULL);
4419
Radek Krejci76512572015-08-04 09:47:08 +02004420 leaf->nodetype = LYS_LEAF;
4421 leaf->prev = (struct lys_node *)leaf;
4422 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004423
Radek Krejci07d0fb92017-01-13 14:11:05 +01004424 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004425 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4426 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4427 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004428 goto error;
4429 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004430
Michal Vasko3e3228d2017-02-24 14:55:32 +01004431 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004432
Radek Krejcic189a952016-07-11 15:27:07 +02004433 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004434 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004435 goto error;
4436 }
4437
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004438 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004439 if (strcmp(sub->ns->value, LY_NSYIN)) {
4440 /* extension */
4441 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004442 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004443 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004444 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004445 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004446 goto error;
4447 }
Michal Vasko88c29542015-11-27 14:57:53 +01004448 /* HACK for unres */
4449 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004450 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004451 /* postpone type resolution when if-feature parsing is done since we need
4452 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004453 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004454 } else if (!strcmp(sub->name, "default")) {
4455 if (leaf->dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004456 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004457 goto error;
4458 }
4459 GETVAL(value, sub, "value");
4460 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci1abcdae2017-01-18 14:14:18 +01004461
Radek Krejci8d6b7422017-02-03 14:42:13 +01004462 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
Radek Krejci1abcdae2017-01-18 14:14:18 +01004463 goto error;
4464 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004465 } else if (!strcmp(sub->name, "units")) {
4466 if (leaf->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004467 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004468 goto error;
4469 }
4470 GETVAL(value, sub, "name");
4471 leaf->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004472
Radek Krejci8d6b7422017-02-03 14:42:13 +01004473 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004474 goto error;
4475 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004476 } else if (!strcmp(sub->name, "mandatory")) {
4477 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004478 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004479 goto error;
4480 }
4481 /* just checking the flags in leaf is not sufficient, we would allow
4482 * multiple mandatory statements with the "false" value
4483 */
4484 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02004485
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004486 GETVAL(value, sub, "value");
4487 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004488 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004489 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004490 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004491 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004492 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004493 goto error;
4494 } /* else false is the default value, so we can ignore it */
Radek Krejcifccd1442017-01-16 10:26:57 +01004495
Radek Krejci8d6b7422017-02-03 14:42:13 +01004496 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004497 goto error;
4498 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004499 } else if (!strcmp(sub->name, "when")) {
4500 if (leaf->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004501 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004502 goto error;
4503 }
4504
Radek Krejci5323b492017-01-16 15:40:11 +01004505 leaf->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004506 if (!leaf->when) {
4507 goto error;
4508 }
4509
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004510 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02004511 c_must++;
4512 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004513 } else if (!strcmp(sub->name, "if-feature")) {
4514 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004515 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004516
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004517 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004518 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004519 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004520 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004521
Michal Vasko88c29542015-11-27 14:57:53 +01004522 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004523 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004524
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004525 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004526 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004527 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004528 goto error;
4529 }
Michal Vasko478c4652016-07-21 12:55:01 +02004530 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004531 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "mandatory", "leaf");
Michal Vasko51e5c582017-01-19 14:16:39 +01004532 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL,
Michal Vasko478c4652016-07-21 12:55:01 +02004533 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
4534 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004535 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004537 /* middle part - process nodes with cardinality of 0..n */
4538 if (c_must) {
4539 leaf->must = calloc(c_must, sizeof *leaf->must);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004540 LY_CHECK_ERR_GOTO(!leaf->must, LOGMEM, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004541 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004542 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004543 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004544 LY_CHECK_ERR_GOTO(!leaf->iffeature, LOGMEM, error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004545 }
Radek Krejcie534c132016-11-23 13:32:31 +01004546 if (c_ext) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004547 /* some extensions may be already present from the substatements */
4548 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004549 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejcifccd1442017-01-16 10:26:57 +01004550 retval->ext = reallocated;
4551
4552 /* init memory */
4553 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004554 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004555
Radek Krejcie534c132016-11-23 13:32:31 +01004556 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4557 if (strcmp(sub->ns->value, LY_NSYIN)) {
4558 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004559 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 +01004560 retval->ext_size++;
4561 if (r) {
4562 goto error;
4563 }
4564 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004565 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004566 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004567 if (r) {
4568 goto error;
4569 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004570 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004571 r = fill_yin_iffeature(retval, 0, sub, &leaf->iffeature[leaf->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004572 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004573 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004574 goto error;
4575 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004576 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004577 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004578
Radek Krejcicbb473e2016-09-16 14:48:32 +02004579 /* finalize type parsing */
4580 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
4581 leaf->type.der = NULL;
4582 goto error;
4583 }
4584
4585 /* check default value (if not defined, there still could be some restrictions
4586 * that need to be checked against a default value from a derived type) */
Radek Krejciab08f0f2017-03-09 16:37:15 +01004587 if (!(options & LYS_PARSE_OPT_INGRP) &&
4588 (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT,
4589 (struct lys_node *)(&leaf->dflt)) == -1)) {
Radek Krejcicbb473e2016-09-16 14:48:32 +02004590 goto error;
4591 }
4592
Michal Vasko508a50d2016-09-07 14:50:33 +02004593 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01004594 if (leaf->when || leaf->must) {
4595 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004596 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004597 goto error;
4598 }
4599 } else {
4600 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4601 goto error;
4602 }
4603 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004604 }
4605
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004606 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004607
4608error:
4609
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004610 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004611
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004612 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004613}
4614
Michal Vasko0d343d12015-08-24 14:57:36 +02004615/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004616static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004617read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004618 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004619{
Radek Krejci76512572015-08-04 09:47:08 +02004620 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004621 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004622 struct lyxml_elem *sub, *next;
4623 const char *value;
4624 char *endptr;
4625 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004626 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004627 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004628 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejci5323b492017-01-16 15:40:11 +01004629 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004630
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004631 llist = calloc(1, sizeof *llist);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004632 LY_CHECK_ERR_RETURN(!llist, LOGMEM, NULL);
4633
Radek Krejci76512572015-08-04 09:47:08 +02004634 llist->nodetype = LYS_LEAFLIST;
4635 llist->prev = (struct lys_node *)llist;
4636 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004637
Radek Krejci07d0fb92017-01-13 14:11:05 +01004638 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004639 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4640 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4641 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004642 goto error;
4643 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004644
Michal Vasko3e3228d2017-02-24 14:55:32 +01004645 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004646
Radek Krejcic189a952016-07-11 15:27:07 +02004647 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004648 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004649 goto error;
4650 }
4651
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004652 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004653 if (strcmp(sub->ns->value, LY_NSYIN)) {
4654 /* extension */
4655 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004656 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004657 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004658 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004659 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004660 goto error;
4661 }
Michal Vasko88c29542015-11-27 14:57:53 +01004662 /* HACK for unres */
4663 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004664 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004665 /* postpone type resolution when if-feature parsing is done since we need
4666 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004667 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004668 } else if (!strcmp(sub->name, "units")) {
4669 if (llist->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004670 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004671 goto error;
4672 }
4673 GETVAL(value, sub, "name");
4674 llist->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004675
Radek Krejci8d6b7422017-02-03 14:42:13 +01004676 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004677 goto error;
4678 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004679 } else if (!strcmp(sub->name, "ordered-by")) {
4680 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004681 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004682 goto error;
4683 }
4684 /* just checking the flags in llist is not sufficient, we would
4685 * allow multiple ordered-by statements with the "system" value
4686 */
4687 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004688
Radek Krejci1574a8d2015-08-03 14:16:52 +02004689 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004690 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4691 * state data
4692 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004693 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004694 continue;
4695 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004696
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004697 GETVAL(value, sub, "value");
4698 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004699 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004700 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004701 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004702 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02004703 } /* else system is the default value, so we can ignore it */
4704
Radek Krejci8d6b7422017-02-03 14:42:13 +01004705 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004706 goto error;
4707 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004708 } else if (!strcmp(sub->name, "must")) {
4709 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02004710 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004711 } else if (!strcmp(sub->name, "if-feature")) {
4712 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004713 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02004714 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004715 /* read the default's extension instances */
Radek Krejci8d6b7422017-02-03 14:42:13 +01004716 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 +01004717 goto error;
4718 }
4719
Radek Krejcid5a5c282016-08-15 15:38:08 +02004720 c_dflt++;
4721 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004722
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004723 } else if (!strcmp(sub->name, "min-elements")) {
4724 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004725 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004726 goto error;
4727 }
4728 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004729
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004730 GETVAL(value, sub, "value");
4731 while (isspace(value[0])) {
4732 value++;
4733 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004734
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004735 /* convert it to uint32_t */
4736 errno = 0;
4737 endptr = NULL;
4738 val = strtoul(value, &endptr, 10);
4739 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004740 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004741 goto error;
4742 }
4743 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004744 if (llist->max && (llist->min > llist->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004745 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004746 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004747 goto error;
4748 }
Radek Krejci5323b492017-01-16 15:40:11 +01004749
Radek Krejci8d6b7422017-02-03 14:42:13 +01004750 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004751 goto error;
4752 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004753 } else if (!strcmp(sub->name, "max-elements")) {
4754 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004755 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004756 goto error;
4757 }
4758 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004759
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004760 GETVAL(value, sub, "value");
4761 while (isspace(value[0])) {
4762 value++;
4763 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004764
Radek Krejci0d7b2472016-02-12 11:11:03 +01004765 if (!strcmp(value, "unbounded")) {
4766 llist->max = 0;
4767 } else {
4768 /* convert it to uint32_t */
4769 errno = 0;
4770 endptr = NULL;
4771 val = strtoul(value, &endptr, 10);
4772 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004773 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004774 goto error;
4775 }
4776 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004777 if (llist->min > llist->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004778 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004779 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004780 goto error;
4781 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004782 }
Radek Krejci5323b492017-01-16 15:40:11 +01004783
Radek Krejci8d6b7422017-02-03 14:42:13 +01004784 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004785 goto error;
4786 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004787 } else if (!strcmp(sub->name, "when")) {
4788 if (llist->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004789 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004790 goto error;
4791 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004792
Radek Krejci5323b492017-01-16 15:40:11 +01004793 llist->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004794 if (!llist->when) {
4795 goto error;
4796 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004797 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004798 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004799 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004800 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004801
Michal Vasko88c29542015-11-27 14:57:53 +01004802 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004803 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004804
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004805 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004806 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004807 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004808 goto error;
4809 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004810
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004811 /* middle part - process nodes with cardinality of 0..n */
4812 if (c_must) {
4813 llist->must = calloc(c_must, sizeof *llist->must);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004814 LY_CHECK_ERR_GOTO(!llist->must, LOGMEM, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004815 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004816 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004817 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004818 LY_CHECK_ERR_GOTO(!llist->iffeature, LOGMEM, error);
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);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004822 LY_CHECK_ERR_GOTO(!llist->dflt, LOGMEM, error);
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004823 }
Radek Krejcie534c132016-11-23 13:32:31 +01004824 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01004825 /* some extensions may be already present from the substatements */
4826 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004827 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejci5323b492017-01-16 15:40:11 +01004828 retval->ext = reallocated;
4829
4830 /* init memory */
4831 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004832 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004833
Radek Krejcie534c132016-11-23 13:32:31 +01004834 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4835 if (strcmp(sub->ns->value, LY_NSYIN)) {
4836 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004837 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 +01004838 retval->ext_size++;
4839 if (r) {
4840 goto error;
4841 }
4842 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004843 r = fill_yin_must(module, sub, &llist->must[llist->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004844 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004845 if (r) {
4846 goto error;
4847 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004848 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004849 r = fill_yin_iffeature(retval, 0, sub, &llist->iffeature[llist->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004850 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004851 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004852 goto error;
4853 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004854 } else if (!strcmp(sub->name, "default")) {
4855 GETVAL(value, sub, "value");
4856
Radek Krejciac1a52c2016-09-15 14:42:40 +02004857 /* check for duplicity in case of configuration data,
4858 * in case of status data duplicities are allowed */
4859 if (llist->flags & LYS_CONFIG_W) {
4860 for (r = 0; r < llist->dflt_size; r++) {
4861 if (ly_strequal(llist->dflt[r], value, 1)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004862 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, "default");
Michal Vasko51e5c582017-01-19 14:16:39 +01004863 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "Duplicated default value \"%s\".", value);
Radek Krejciac1a52c2016-09-15 14:42:40 +02004864 goto error;
4865 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004866 }
4867 }
4868 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004869 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004870 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004871
Radek Krejcicbb473e2016-09-16 14:48:32 +02004872 /* finalize type parsing */
4873 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
4874 llist->type.der = NULL;
4875 goto error;
4876 }
4877
Radek Krejcid5a5c282016-08-15 15:38:08 +02004878 if (llist->dflt_size && llist->min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004879 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "min-elements", "leaf-list");
Michal Vasko51e5c582017-01-19 14:16:39 +01004880 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02004881 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
4882 goto error;
4883 }
4884
4885 /* check default value (if not defined, there still could be some restrictions
4886 * that need to be checked against a default value from a derived type) */
4887 for (r = 0; r < llist->dflt_size; r++) {
Radek Krejciab08f0f2017-03-09 16:37:15 +01004888 if (!(options & LYS_PARSE_OPT_INGRP) &&
4889 (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
4890 (struct lys_node *)(&llist->dflt[r])) == -1)) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02004891 goto error;
Radek Krejci25d782a2015-05-22 15:03:23 +02004892 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004893 }
4894
Michal Vasko508a50d2016-09-07 14:50:33 +02004895 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01004896 if (llist->when || llist->must) {
4897 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01004898 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01004899 goto error;
4900 }
4901 } else {
4902 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
4903 goto error;
4904 }
4905 }
Michal Vasko508a50d2016-09-07 14:50:33 +02004906 }
4907
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004908 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004909
4910error:
4911
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004912 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004913
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004914 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004915}
4916
Michal Vasko0d343d12015-08-24 14:57:36 +02004917/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004918static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01004919read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02004920 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004921{
Radek Krejci1d82ef62015-08-07 14:44:40 +02004922 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02004923 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004924 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01004925 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01004926 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004927 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejci5c08a992016-11-02 13:30:04 +01004928 const char *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004929 char *auxs;
4930 unsigned long val;
Radek Krejcie36d7c72017-01-17 16:12:30 +01004931 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004932
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004933 /* init */
4934 memset(&root, 0, sizeof root);
4935 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02004936
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004937 list = calloc(1, sizeof *list);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004938 LY_CHECK_ERR_RETURN(!list, LOGMEM, NULL);
4939
Radek Krejci76512572015-08-04 09:47:08 +02004940 list->nodetype = LYS_LIST;
4941 list->prev = (struct lys_node *)list;
4942 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004943
Radek Krejci07d0fb92017-01-13 14:11:05 +01004944 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01004945 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
4946 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
4947 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004948 goto error;
4949 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004950
Michal Vasko3e3228d2017-02-24 14:55:32 +01004951 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02004952
Radek Krejcic189a952016-07-11 15:27:07 +02004953 /* insert the node into the schema tree */
4954 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4955 goto error;
4956 }
4957
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004958 /* process list's specific children */
4959 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004960 if (strcmp(sub->ns->value, LY_NSYIN)) {
4961 /* extension */
4962 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004963 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02004964
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004965 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01004966 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004967 !strcmp(sub->name, "leaf-list") ||
4968 !strcmp(sub->name, "leaf") ||
4969 !strcmp(sub->name, "list") ||
4970 !strcmp(sub->name, "choice") ||
4971 !strcmp(sub->name, "uses") ||
4972 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004973 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01004974 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02004975 !strcmp(sub->name, "action") ||
4976 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004977 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004978 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004979
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004980 /* array counters */
4981 } else if (!strcmp(sub->name, "key")) {
4982 /* check cardinality 0..1 */
4983 if (list->keys_size) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004984 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004985 goto error;
4986 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004987
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004988 /* count the number of keys */
4989 GETVAL(value, sub, "value");
Radek Krejci5c08a992016-11-02 13:30:04 +01004990 list->keys_str = lydict_insert(module->ctx, value, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004991 while ((value = strpbrk(value, " \t\n"))) {
4992 list->keys_size++;
4993 while (isspace(*value)) {
4994 value++;
4995 }
4996 }
4997 list->keys_size++;
4998 list->keys = calloc(list->keys_size, sizeof *list->keys);
Radek Krejcia8d111f2017-05-31 13:57:37 +02004999 LY_CHECK_ERR_GOTO(!list->keys, LOGMEM, error);
Radek Krejcie36d7c72017-01-17 16:12:30 +01005000
Radek Krejci8d6b7422017-02-03 14:42:13 +01005001 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_KEY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005002 goto error;
5003 }
5004 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005005 } else if (!strcmp(sub->name, "unique")) {
5006 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005007 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005008 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005009 } else if (!strcmp(sub->name, "typedef")) {
5010 c_tpdf++;
5011 } else if (!strcmp(sub->name, "must")) {
5012 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005013 } else if (!strcmp(sub->name, "if-feature")) {
5014 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02005015
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005016 /* optional stetments */
5017 } else if (!strcmp(sub->name, "ordered-by")) {
5018 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005019 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005020 goto error;
5021 }
5022 /* just checking the flags in llist is not sufficient, we would
5023 * allow multiple ordered-by statements with the "system" value
5024 */
5025 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005026
Radek Krejci1574a8d2015-08-03 14:16:52 +02005027 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005028 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
5029 * state data
5030 */
Michal Vasko345da0a2015-12-02 10:35:55 +01005031 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005032 continue;
5033 }
Radek Krejci345ad742015-06-03 11:04:18 +02005034
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005035 GETVAL(value, sub, "value");
5036 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02005037 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005038 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005039 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005040 goto error;
Radek Krejcie36d7c72017-01-17 16:12:30 +01005041 } /* else system is the default value, so we can ignore it */
5042
Radek Krejci8d6b7422017-02-03 14:42:13 +01005043 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005044 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005045 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005046 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005047 } else if (!strcmp(sub->name, "min-elements")) {
5048 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005049 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005050 goto error;
5051 }
5052 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005053
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005054 GETVAL(value, sub, "value");
5055 while (isspace(value[0])) {
5056 value++;
5057 }
Radek Krejci345ad742015-06-03 11:04:18 +02005058
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005059 /* convert it to uint32_t */
5060 errno = 0;
5061 auxs = NULL;
5062 val = strtoul(value, &auxs, 10);
5063 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005064 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005065 goto error;
5066 }
5067 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005068 if (list->max && (list->min > list->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005069 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01005070 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005071 lyxml_free(module->ctx, sub);
5072 goto error;
5073 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005074 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005075 goto error;
5076 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005077 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005078 } else if (!strcmp(sub->name, "max-elements")) {
5079 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005080 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005081 goto error;
5082 }
5083 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005084
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005085 GETVAL(value, sub, "value");
5086 while (isspace(value[0])) {
5087 value++;
5088 }
Radek Krejci345ad742015-06-03 11:04:18 +02005089
Radek Krejci0d7b2472016-02-12 11:11:03 +01005090 if (!strcmp(value, "unbounded")) {
5091 list->max = 0;;
5092 } else {
5093 /* convert it to uint32_t */
5094 errno = 0;
5095 auxs = NULL;
5096 val = strtoul(value, &auxs, 10);
5097 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005098 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01005099 goto error;
5100 }
5101 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005102 if (list->min > list->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005103 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01005104 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005105 goto error;
5106 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005107 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01005108 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005109 goto error;
5110 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005111 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005112 } else if (!strcmp(sub->name, "when")) {
5113 if (list->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005114 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005115 goto error;
5116 }
5117
Radek Krejci5323b492017-01-16 15:40:11 +01005118 list->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005119 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005120 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005121 goto error;
5122 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005123 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005124 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005125 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005126 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005127 }
5128 }
Radek Krejci345ad742015-06-03 11:04:18 +02005129
Michal Vaskoe022a562016-09-27 14:24:15 +02005130 /* check - if list is configuration, key statement is mandatory
5131 * (but only if we are not in a grouping or augment, then the check is deferred) */
Radek Krejcif95b6292017-02-13 15:57:37 +01005132 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT | LYS_EXT)); node = node->parent);
Radek Krejci5c08a992016-11-02 13:30:04 +01005133 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys_str) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005134 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005135 goto error;
5136 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005137
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005138 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5139 if (c_tpdf) {
5140 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005141 LY_CHECK_ERR_GOTO(!list->tpdf, LOGMEM, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005142 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005143 if (c_must) {
5144 list->must = calloc(c_must, sizeof *list->must);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005145 LY_CHECK_ERR_GOTO(!list->must, LOGMEM, error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005146 }
5147 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005148 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005149 LY_CHECK_ERR_GOTO(!list->iffeature, LOGMEM, error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005150 }
Radek Krejcie534c132016-11-23 13:32:31 +01005151 if (c_ext) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005152 /* some extensions may be already present from the substatements */
5153 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005154 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejcie36d7c72017-01-17 16:12:30 +01005155 retval->ext = reallocated;
5156
5157 /* init memory */
5158 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005159 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005160
Radek Krejcie534c132016-11-23 13:32:31 +01005161 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5162 if (strcmp(sub->ns->value, LY_NSYIN)) {
5163 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005164 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 +01005165 retval->ext_size++;
5166 if (r) {
5167 goto error;
5168 }
5169 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005170 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
5171 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005172 if (r) {
5173 goto error;
5174 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005175 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005176 r = fill_yin_iffeature(retval, 0, sub, &list->iffeature[list->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005177 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005178 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005179 goto error;
5180 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005181 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005182 r = fill_yin_must(module, sub, &list->must[list->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005183 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005184 if (r) {
5185 goto error;
5186 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005187 }
5188 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005189
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005190 /* last part - process data nodes */
5191 LY_TREE_FOR_SAFE(root.child, next, sub) {
5192 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005193 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005194 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005195 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005196 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005197 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005198 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005199 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005200 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005201 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005202 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005203 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005204 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005205 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005206 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005207 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005208 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005209 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005210 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005211 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005212 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005213 node = read_yin_notif(module, retval, sub, options, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005214 } else {
5215 LOGINT;
5216 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005217 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005218 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005219 goto error;
5220 }
Radek Krejci73adb602015-07-02 18:07:40 +02005221
Michal Vasko345da0a2015-12-02 10:35:55 +01005222 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005223 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005224
Radek Krejci5c08a992016-11-02 13:30:04 +01005225 if (list->keys_str) {
5226 /* check that we are not in grouping */
5227 for (node = parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
5228 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01005229 goto error;
5230 }
5231 } /* 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 +02005232
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005233 /* process unique statements */
5234 if (c_uniq) {
5235 list->unique = calloc(c_uniq, sizeof *list->unique);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005236 LY_CHECK_ERR_GOTO(!list->unique, LOGMEM, error);
Radek Krejci1e9b9992015-06-04 17:57:04 +02005237
Radek Krejci461efb92016-02-12 15:52:18 +01005238 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
5239 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
5240 list->unique_size++;
5241 if (r) {
5242 goto error;
5243 }
5244
Radek Krejci8d6b7422017-02-03 14:42:13 +01005245 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub,
Radek Krejcie36d7c72017-01-17 16:12:30 +01005246 LYEXT_SUBSTMT_UNIQUE, list->unique_size - 1, unres)) {
5247 goto error;
5248 }
Radek Krejci461efb92016-02-12 15:52:18 +01005249 lyxml_free(module->ctx, sub);
5250 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005251 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005252
Michal Vasko508a50d2016-09-07 14:50:33 +02005253 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01005254 if (list->when || list->must) {
5255 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005256 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005257 goto error;
5258 }
5259 } else {
5260 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5261 goto error;
5262 }
5263 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005264 }
5265
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005266 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005267
5268error:
5269
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005270 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005271 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005272 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005273 }
5274 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005275 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005276 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005278 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005279}
5280
Michal Vasko0d343d12015-08-24 14:57:36 +02005281/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005282static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005283read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005284 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005285{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005286 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005287 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005288 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005289 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005290 const char *value;
Radek Krejci07d0fb92017-01-13 14:11:05 +01005291 void *reallocated;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005292 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005293 int c_tpdf = 0, c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005294
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005295 /* init */
5296 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005298 cont = calloc(1, sizeof *cont);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005299 LY_CHECK_ERR_RETURN(!cont, LOGMEM, NULL);
5300
Radek Krejci76512572015-08-04 09:47:08 +02005301 cont->nodetype = LYS_CONTAINER;
5302 cont->prev = (struct lys_node *)cont;
5303 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005304
Radek Krejci07d0fb92017-01-13 14:11:05 +01005305 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005306 OPT_IDENT | OPT_MODULE | ((options & LYS_PARSE_OPT_CFG_IGNORE) ? OPT_CFG_IGNORE :
5307 (options & LYS_PARSE_OPT_CFG_NOINHERIT) ? OPT_CFG_PARSE : OPT_CFG_PARSE | OPT_CFG_INHERIT),
5308 unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005309 goto error;
5310 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005311
Michal Vasko3e3228d2017-02-24 14:55:32 +01005312 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005313
Radek Krejcic189a952016-07-11 15:27:07 +02005314 /* insert the node into the schema tree */
5315 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5316 goto error;
5317 }
5318
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005319 /* process container's specific children */
5320 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005321 if (strcmp(sub->ns->value, LY_NSYIN)) {
5322 /* extension */
5323 c_ext++;
5324 } else if (!strcmp(sub->name, "presence")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005325 if (cont->presence) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005326 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005327 goto error;
5328 }
5329 GETVAL(value, sub, "value");
5330 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02005331
Radek Krejci8d6b7422017-02-03 14:42:13 +01005332 if (lyp_yin_parse_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005333 goto error;
5334 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005335 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005336 } else if (!strcmp(sub->name, "when")) {
5337 if (cont->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005338 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005339 goto error;
5340 }
5341
Radek Krejci5323b492017-01-16 15:40:11 +01005342 cont->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005343 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005344 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005345 goto error;
5346 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005347 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02005348
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005349 /* data statements */
5350 } else if (!strcmp(sub->name, "container") ||
5351 !strcmp(sub->name, "leaf-list") ||
5352 !strcmp(sub->name, "leaf") ||
5353 !strcmp(sub->name, "list") ||
5354 !strcmp(sub->name, "choice") ||
5355 !strcmp(sub->name, "uses") ||
5356 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005357 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005358 !strcmp(sub->name, "anydata") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005359 !strcmp(sub->name, "action") ||
5360 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005361 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005362 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005363
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005364 /* array counters */
5365 } else if (!strcmp(sub->name, "typedef")) {
5366 c_tpdf++;
5367 } else if (!strcmp(sub->name, "must")) {
5368 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005369 } else if (!strcmp(sub->name, "if-feature")) {
5370 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005371 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005372 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005373 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005374 }
5375 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005376
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005377 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5378 if (c_tpdf) {
5379 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005380 LY_CHECK_ERR_GOTO(!cont->tpdf, LOGMEM, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005381 }
5382 if (c_must) {
5383 cont->must = calloc(c_must, sizeof *cont->must);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005384 LY_CHECK_ERR_GOTO(!cont->must, LOGMEM, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005385 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005386 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005387 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005388 LY_CHECK_ERR_GOTO(!cont->iffeature, LOGMEM, error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005389 }
Radek Krejcie534c132016-11-23 13:32:31 +01005390 if (c_ext) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01005391 /* some extensions may be already present from the substatements */
5392 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005393 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejci07d0fb92017-01-13 14:11:05 +01005394 retval->ext = reallocated;
5395
5396 /* init memory */
5397 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005398 }
Radek Krejci800af702015-06-02 13:46:01 +02005399
Radek Krejcie534c132016-11-23 13:32:31 +01005400 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5401 if (strcmp(sub->ns->value, LY_NSYIN)) {
5402 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005403 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 +01005404 retval->ext_size++;
5405 if (r) {
5406 goto error;
5407 }
5408 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005409 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
5410 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005411 if (r) {
5412 goto error;
5413 }
5414 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005415 r = fill_yin_must(module, sub, &cont->must[cont->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005416 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005417 if (r) {
5418 goto error;
5419 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005420 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005421 r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005422 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005423 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005424 goto error;
5425 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005426 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005427 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005428
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005429 /* last part - process data nodes */
5430 LY_TREE_FOR_SAFE(root.child, next, sub) {
5431 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005432 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005433 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005434 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005435 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005436 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005437 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005438 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005439 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005440 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005441 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005442 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005443 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005444 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005445 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005446 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005447 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005448 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005449 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005450 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005451 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005452 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005453 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005454 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005455 goto error;
5456 }
Radek Krejci73adb602015-07-02 18:07:40 +02005457
Michal Vasko345da0a2015-12-02 10:35:55 +01005458 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005459 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005460
Michal Vasko508a50d2016-09-07 14:50:33 +02005461 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01005462 if (cont->when || cont->must) {
5463 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005464 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005465 goto error;
5466 }
5467 } else {
5468 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5469 goto error;
5470 }
5471 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005472 }
5473
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005474 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005475
5476error:
5477
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005478 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005479 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005480 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005481 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005482
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005483 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005484}
5485
Michal Vasko0d343d12015-08-24 14:57:36 +02005486/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005487static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01005488read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int options,
Michal Vaskof02e3742015-08-05 16:27:02 +02005489 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005490{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005491 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005492 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005493 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005494 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005495 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005496 int c_tpdf = 0, c_ext = 0;
Radek Krejcifdc0d702017-01-23 15:58:38 +01005497 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005498
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005499 /* init */
5500 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005501
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005502 grp = calloc(1, sizeof *grp);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005503 LY_CHECK_ERR_RETURN(!grp, LOGMEM, NULL);
5504
Radek Krejci76512572015-08-04 09:47:08 +02005505 grp->nodetype = LYS_GROUPING;
5506 grp->prev = (struct lys_node *)grp;
5507 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005508
Radek Krejci07d0fb92017-01-13 14:11:05 +01005509 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE , unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005510 goto error;
5511 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005512
Michal Vasko3e3228d2017-02-24 14:55:32 +01005513 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005514
Radek Krejcic189a952016-07-11 15:27:07 +02005515 /* insert the node into the schema tree */
5516 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5517 goto error;
5518 }
5519
Radek Krejci1d82ef62015-08-07 14:44:40 +02005520 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005521 if (strcmp(sub->ns->value, LY_NSYIN)) {
5522 /* extension */
5523 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005524
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005525 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005526 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005527 !strcmp(sub->name, "leaf-list") ||
5528 !strcmp(sub->name, "leaf") ||
5529 !strcmp(sub->name, "list") ||
5530 !strcmp(sub->name, "choice") ||
5531 !strcmp(sub->name, "uses") ||
5532 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005533 !strcmp(sub->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005534 !strcmp(sub->name, "anydata") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02005535 !strcmp(sub->name, "action") ||
5536 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005537 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005538 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005539
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005540 /* array counters */
5541 } else if (!strcmp(sub->name, "typedef")) {
5542 c_tpdf++;
5543 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005544 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005545 goto error;
5546 }
5547 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005548
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005549 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5550 if (c_tpdf) {
5551 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005552 LY_CHECK_ERR_GOTO(!grp->tpdf, LOGMEM, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005553 }
Radek Krejcie534c132016-11-23 13:32:31 +01005554 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01005555 /* some extensions may be already present from the substatements */
5556 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005557 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01005558 retval->ext = reallocated;
5559
5560 /* init memory */
5561 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005562 }
Radek Krejcie534c132016-11-23 13:32:31 +01005563 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5564 if (strcmp(sub->ns->value, LY_NSYIN)) {
5565 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005566 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 +01005567 retval->ext_size++;
5568 if (r) {
5569 goto error;
5570 }
5571 } else {
5572 /* typedef */
5573 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
5574 grp->tpdf_size++;
5575 if (r) {
5576 goto error;
5577 }
5578 }
5579 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005580
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005581 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02005582 if (!root.child) {
5583 LOGWRN("Grouping \"%s\" without children.", retval->name);
5584 }
Radek Krejci7212e0a2017-03-08 15:58:22 +01005585 options |= LYS_PARSE_OPT_INGRP;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005586 LY_TREE_FOR_SAFE(root.child, next, sub) {
5587 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005588 node = read_yin_container(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005589 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005590 node = read_yin_leaflist(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005591 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005592 node = read_yin_leaf(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005593 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005594 node = read_yin_list(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005595 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005596 node = read_yin_choice(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005597 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005598 node = read_yin_uses(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005599 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005600 node = read_yin_grouping(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005601 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005602 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005603 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005604 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005605 } else if (!strcmp(sub->name, "action")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005606 node = read_yin_rpc_action(module, retval, sub, options, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02005607 } else if (!strcmp(sub->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005608 node = read_yin_notif(module, retval, sub, options, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005609 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005610 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005611 goto error;
5612 }
Radek Krejci73adb602015-07-02 18:07:40 +02005613
Michal Vasko345da0a2015-12-02 10:35:55 +01005614 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005615 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005616
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005617 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005618
5619error:
5620
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005621 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005622 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005623 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005624 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005625
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005626 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005627}
5628
Michal Vasko0d343d12015-08-24 14:57:36 +02005629/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005630static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005631read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005632 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005633{
Radek Krejcie0674f82015-06-15 13:58:51 +02005634 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005635 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02005636 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02005637 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005638 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005639 int c_tpdf = 0, c_must = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005640
Radek Krejcie0674f82015-06-15 13:58:51 +02005641 /* init */
5642 memset(&root, 0, sizeof root);
5643
Michal Vasko38d01f72015-06-15 09:41:06 +02005644 inout = calloc(1, sizeof *inout);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005645 LY_CHECK_ERR_RETURN(!inout, LOGMEM, NULL);
Radek Krejci6acc8012015-08-13 09:07:04 +02005646 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005647
5648 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02005649 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005650 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005651 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02005652 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005653 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005654 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02005655 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02005656 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02005657 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005658 }
5659
Radek Krejci76512572015-08-04 09:47:08 +02005660 retval = (struct lys_node *)inout;
Radek Krejcie7770892017-01-24 13:18:01 +01005661 retval->module = module;
Michal Vaskoebeac942015-06-15 12:11:50 +02005662
Michal Vasko3e3228d2017-02-24 14:55:32 +01005663 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005664
Radek Krejcic189a952016-07-11 15:27:07 +02005665 /* insert the node into the schema tree */
5666 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5667 goto error;
5668 }
5669
Michal Vasko38d01f72015-06-15 09:41:06 +02005670 /* data statements */
5671 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie7770892017-01-24 13:18:01 +01005672 if (!sub->ns) {
5673 /* garbage */
5674 lyxml_free(module->ctx, sub);
5675 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01005676 /* extension */
5677 c_ext++;
5678 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005679 !strcmp(sub->name, "leaf-list") ||
5680 !strcmp(sub->name, "leaf") ||
5681 !strcmp(sub->name, "list") ||
5682 !strcmp(sub->name, "choice") ||
5683 !strcmp(sub->name, "uses") ||
5684 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005685 !strcmp(sub->name, "anyxml") ||
5686 !strcmp(sub->name, "anydata")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005687 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005688 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005689
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005690 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005691 } else if (!strcmp(sub->name, "typedef")) {
5692 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02005693
Radek Krejci1a31efe2016-07-29 11:04:16 +02005694 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005695 c_must++;
5696
Michal Vasko38d01f72015-06-15 09:41:06 +02005697 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005698 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005699 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005700 }
5701 }
5702
5703 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5704 if (c_tpdf) {
5705 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005706 LY_CHECK_ERR_GOTO(!inout->tpdf, LOGMEM, error);
Michal Vasko38d01f72015-06-15 09:41:06 +02005707 }
Radek Krejci19332802016-07-29 10:39:46 +02005708 if (c_must) {
5709 inout->must = calloc(c_must, sizeof *inout->must);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005710 LY_CHECK_ERR_GOTO(!inout->must, LOGMEM, error);
Radek Krejci19332802016-07-29 10:39:46 +02005711 }
Radek Krejcie534c132016-11-23 13:32:31 +01005712 if (c_ext) {
5713 inout->ext = calloc(c_ext, sizeof *inout->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005714 LY_CHECK_ERR_GOTO(!inout->ext, LOGMEM, error);
Radek Krejcie534c132016-11-23 13:32:31 +01005715 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005716
Radek Krejcie534c132016-11-23 13:32:31 +01005717 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5718 if (strcmp(sub->ns->value, LY_NSYIN)) {
5719 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005720 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 +01005721 retval->ext_size++;
5722 if (r) {
5723 goto error;
5724 }
5725 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005726 r = fill_yin_must(module, sub, &inout->must[inout->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02005727 inout->must_size++;
5728 if (r) {
5729 goto error;
5730 }
5731 } else { /* typedef */
5732 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
5733 inout->tpdf_size++;
5734 if (r) {
5735 goto error;
5736 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005737 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005738 }
5739
5740 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01005741 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko38d01f72015-06-15 09:41:06 +02005742 LY_TREE_FOR_SAFE(root.child, next, sub) {
5743 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005744 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005745 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005746 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005747 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005748 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005749 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005750 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005751 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005752 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005753 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005754 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005755 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005756 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005757 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005758 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005759 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005760 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005761 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005762 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005763 goto error;
5764 }
Radek Krejci73adb602015-07-02 18:07:40 +02005765
Michal Vasko345da0a2015-12-02 10:35:55 +01005766 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005767 }
5768
Michal Vasko508a50d2016-09-07 14:50:33 +02005769 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01005770 if (inout->must) {
5771 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005772 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005773 goto error;
5774 }
5775 } else {
5776 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5777 goto error;
5778 }
5779 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005780 }
5781
Michal Vasko38d01f72015-06-15 09:41:06 +02005782 return retval;
5783
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005784error:
Michal Vasko38d01f72015-06-15 09:41:06 +02005785
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005786 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02005787 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005788 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005789 }
5790
5791 return NULL;
5792}
5793
Michal Vasko0d343d12015-08-24 14:57:36 +02005794/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005795static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005796read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005797 int options, struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02005798{
Michal Vaskoc6551b32015-06-16 10:51:43 +02005799 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005800 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005801 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005802 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005803 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005804 int c_tpdf = 0, c_ftrs = 0, c_must = 0, c_ext = 0;
Radek Krejci478ef1d2017-01-24 13:56:09 +01005805 void *reallocated;
Michal Vasko0ea41032015-06-16 08:53:55 +02005806
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005807 if (parent && (module->version < 2)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005808 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "notification");
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005809 return NULL;
5810 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005811
Michal Vaskoc6551b32015-06-16 10:51:43 +02005812 memset(&root, 0, sizeof root);
5813
Michal Vasko0ea41032015-06-16 08:53:55 +02005814 notif = calloc(1, sizeof *notif);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005815 LY_CHECK_ERR_RETURN(!notif, LOGMEM, NULL);
5816
Radek Krejci76512572015-08-04 09:47:08 +02005817 notif->nodetype = LYS_NOTIF;
5818 notif->prev = (struct lys_node *)notif;
5819 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005820
Radek Krejci07d0fb92017-01-13 14:11:05 +01005821 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005822 goto error;
5823 }
5824
Michal Vasko3e3228d2017-02-24 14:55:32 +01005825 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02005826
Radek Krejcic189a952016-07-11 15:27:07 +02005827 /* insert the node into the schema tree */
5828 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5829 goto error;
5830 }
5831
Michal Vasko0ea41032015-06-16 08:53:55 +02005832 /* process rpc's specific children */
5833 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005834 if (strcmp(sub->ns->value, LY_NSYIN)) {
5835 /* extension */
5836 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005837 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02005838
Michal Vasko0ea41032015-06-16 08:53:55 +02005839 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005840 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005841 !strcmp(sub->name, "leaf-list") ||
5842 !strcmp(sub->name, "leaf") ||
5843 !strcmp(sub->name, "list") ||
5844 !strcmp(sub->name, "choice") ||
5845 !strcmp(sub->name, "uses") ||
5846 !strcmp(sub->name, "grouping") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01005847 !strcmp(sub->name, "anyxml") ||
5848 !strcmp(sub->name, "anydata")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005849 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005850 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02005851
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005852 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02005853 } else if (!strcmp(sub->name, "typedef")) {
5854 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005855 } else if (!strcmp(sub->name, "if-feature")) {
5856 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02005857 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005858 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02005859 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005860 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02005861 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02005862 }
5863 }
5864
5865 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5866 if (c_tpdf) {
5867 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005868 LY_CHECK_ERR_GOTO(!notif->tpdf, LOGMEM, error);
Michal Vasko0ea41032015-06-16 08:53:55 +02005869 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005870 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005871 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005872 LY_CHECK_ERR_GOTO(!notif->iffeature, LOGMEM, error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005873 }
Radek Krejci19332802016-07-29 10:39:46 +02005874 if (c_must) {
5875 notif->must = calloc(c_must, sizeof *notif->must);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005876 LY_CHECK_ERR_GOTO(!notif->must, LOGMEM, error);
Michal Vasko0ea41032015-06-16 08:53:55 +02005877 }
Radek Krejcie534c132016-11-23 13:32:31 +01005878 if (c_ext) {
Radek Krejci478ef1d2017-01-24 13:56:09 +01005879 /* some extensions may be already present from the substatements */
5880 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02005881 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejci478ef1d2017-01-24 13:56:09 +01005882 retval->ext = reallocated;
5883
5884 /* init memory */
5885 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005886 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005887
Radek Krejcie534c132016-11-23 13:32:31 +01005888 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5889 if (strcmp(sub->ns->value, LY_NSYIN)) {
5890 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005891 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 +01005892 retval->ext_size++;
5893 if (r) {
5894 goto error;
5895 }
5896 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005897 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
5898 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02005899 if (r) {
5900 goto error;
5901 }
Radek Krejci96299152016-06-22 10:17:50 +02005902 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005903 r = fill_yin_iffeature(retval, 0, sub, &notif->iffeature[notif->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005904 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005905 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005906 goto error;
5907 }
Radek Krejci19332802016-07-29 10:39:46 +02005908 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005909 r = fill_yin_must(module, sub, &notif->must[notif->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02005910 notif->must_size++;
Radek Krejci0b24d752015-07-02 15:02:27 +02005911 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005912 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005913 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005914 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005915 }
5916
5917 /* last part - process data nodes */
Radek Krejci7212e0a2017-03-08 15:58:22 +01005918 options |= LYS_PARSE_OPT_CFG_IGNORE;
Michal Vasko0ea41032015-06-16 08:53:55 +02005919 LY_TREE_FOR_SAFE(root.child, next, sub) {
5920 if (!strcmp(sub->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005921 node = read_yin_container(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005922 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005923 node = read_yin_leaflist(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005924 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005925 node = read_yin_leaf(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005926 } else if (!strcmp(sub->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005927 node = read_yin_list(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005928 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005929 node = read_yin_choice(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005930 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005931 node = read_yin_uses(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005932 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005933 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005934 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005935 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, options, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005936 } else if (!strcmp(sub->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01005937 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, options, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005938 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005939 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005940 goto error;
5941 }
Radek Krejci73adb602015-07-02 18:07:40 +02005942
Michal Vasko345da0a2015-12-02 10:35:55 +01005943 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02005944 }
5945
Michal Vasko508a50d2016-09-07 14:50:33 +02005946 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01005947 if (notif->must) {
5948 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01005949 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01005950 goto error;
5951 }
5952 } else {
5953 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
5954 goto error;
5955 }
5956 }
Michal Vasko508a50d2016-09-07 14:50:33 +02005957 }
5958
Michal Vasko0ea41032015-06-16 08:53:55 +02005959 return retval;
5960
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005961error:
Michal Vasko0ea41032015-06-16 08:53:55 +02005962
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005963 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02005964 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005965 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02005966 }
5967
5968 return NULL;
5969}
5970
Michal Vasko0d343d12015-08-24 14:57:36 +02005971/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005972static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005973read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci7212e0a2017-03-08 15:58:22 +01005974 int options, struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005975{
Radek Krejcie0674f82015-06-15 13:58:51 +02005976 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005977 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005978 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02005979 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02005980 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005981 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0, c_ext = 0;
Radek Krejci94596cf2017-01-24 13:19:16 +01005982 void *reallocated;
Michal Vasko38d01f72015-06-15 09:41:06 +02005983
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005984 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02005985 if (module->version < 2) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005986 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "action");
Michal Vaskobb174852016-07-25 11:00:21 +02005987 return NULL;
5988 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005989 for (node = parent; node; node = lys_parent(node)) {
Radek Krejcia3b19f72016-09-30 13:02:45 +02005990 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005991 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005992 LOGVAL(LYE_INPAR, LY_VLOG_LYS, parent, strnodetype(node->nodetype), "action");
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005993 return NULL;
5994 }
5995 }
5996 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005997
Radek Krejcie0674f82015-06-15 13:58:51 +02005998 /* init */
5999 memset(&root, 0, sizeof root);
6000
Michal Vasko38d01f72015-06-15 09:41:06 +02006001 rpc = calloc(1, sizeof *rpc);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006002 LY_CHECK_ERR_RETURN(!rpc, LOGMEM, NULL);
6003
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006004 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02006005 rpc->prev = (struct lys_node *)rpc;
6006 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02006007
Radek Krejci07d0fb92017-01-13 14:11:05 +01006008 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006009 goto error;
6010 }
6011
Michal Vasko3e3228d2017-02-24 14:55:32 +01006012 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006013
Radek Krejcic189a952016-07-11 15:27:07 +02006014 /* insert the node into the schema tree */
6015 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6016 goto error;
6017 }
6018
Michal Vasko38d01f72015-06-15 09:41:06 +02006019 /* process rpc's specific children */
6020 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006021 if (strcmp(sub->ns->value, LY_NSYIN)) {
6022 /* extension */
6023 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006024 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006025 } else if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006026 if (c_input) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006027 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006028 goto error;
6029 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006030 c_input++;
Michal Vaskof3930de2015-10-22 12:03:59 +02006031 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006032 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006033 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006034 if (c_output) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006035 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006036 goto error;
6037 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006038 c_output++;
Michal Vaskof3930de2015-10-22 12:03:59 +02006039 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006040 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006041
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006042 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02006043 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02006044 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006045 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006046
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006047 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02006048 } else if (!strcmp(sub->name, "typedef")) {
6049 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006050 } else if (!strcmp(sub->name, "if-feature")) {
6051 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006052 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006053 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006054 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02006055 }
6056 }
6057
6058 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6059 if (c_tpdf) {
6060 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006061 LY_CHECK_ERR_GOTO(!rpc->tpdf, LOGMEM, error);
Michal Vasko38d01f72015-06-15 09:41:06 +02006062 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006063 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006064 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006065 LY_CHECK_ERR_GOTO(!rpc->iffeature, LOGMEM, error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006066 }
Radek Krejcie534c132016-11-23 13:32:31 +01006067 if (c_ext) {
Radek Krejci94596cf2017-01-24 13:19:16 +01006068 /* some extensions may be already present from the substatements */
6069 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006070 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejci94596cf2017-01-24 13:19:16 +01006071 retval->ext = reallocated;
6072
6073 /* init memory */
6074 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006075 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006076
Radek Krejcie534c132016-11-23 13:32:31 +01006077 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6078 if (strcmp(sub->ns->value, LY_NSYIN)) {
6079 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006080 r = lyp_yin_fill_ext(retval, LYEXT_PAR_NODE, 0, 0, module, sub, &retval->ext, retval->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01006081 retval->ext_size++;
6082 if (r) {
6083 goto error;
6084 }
6085 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006086 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
6087 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006088 if (r) {
6089 goto error;
6090 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006091 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006092 r = fill_yin_iffeature(retval, 0, sub, &rpc->iffeature[rpc->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006093 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006094 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006095 goto error;
6096 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006097 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006098 }
6099
6100 /* last part - process data nodes */
6101 LY_TREE_FOR_SAFE(root.child, next, sub) {
6102 if (!strcmp(sub->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006103 node = read_yin_grouping(module, retval, sub, options, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006104 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006105 node = read_yin_input_output(module, retval, sub, options, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006106 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006107 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006108 goto error;
6109 }
Radek Krejci73adb602015-07-02 18:07:40 +02006110
Michal Vasko345da0a2015-12-02 10:35:55 +01006111 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006112 }
6113
Michal Vasko38d01f72015-06-15 09:41:06 +02006114 return retval;
6115
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006116error:
Michal Vasko38d01f72015-06-15 09:41:06 +02006117
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006118 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006119 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006120 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006121 }
6122
6123 return NULL;
6124}
6125
Michal Vasko0d343d12015-08-24 14:57:36 +02006126/* logs directly
6127 *
Radek Krejci74705112015-06-05 10:25:44 +02006128 * resolve - referenced grouping should be bounded to the namespace (resolved)
6129 * only when uses does not appear in grouping. In a case of grouping's uses,
6130 * we just get information but we do not apply augment or refine to it.
6131 */
Radek Krejci76512572015-08-04 09:47:08 +02006132static struct lys_node *
Radek Krejci7212e0a2017-03-08 15:58:22 +01006133read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
6134 int options, struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02006135{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006136 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02006137 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006138 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006139 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01006140 int c_ref = 0, c_aug = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006141 int r;
Radek Krejcifdc0d702017-01-23 15:58:38 +01006142 void *reallocated;
Radek Krejci74705112015-06-05 10:25:44 +02006143
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006144 uses = calloc(1, sizeof *uses);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006145 LY_CHECK_ERR_RETURN(!uses, LOGMEM, NULL);
6146
Radek Krejci76512572015-08-04 09:47:08 +02006147 uses->nodetype = LYS_USES;
6148 uses->prev = (struct lys_node *)uses;
6149 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02006150
Radek Krejcia9544502015-08-14 08:24:29 +02006151 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006152 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02006153
Radek Krejci07d0fb92017-01-13 14:11:05 +01006154 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006155 goto error;
6156 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006157
Michal Vasko3e3228d2017-02-24 14:55:32 +01006158 LOGDBG(LY_LDGYIN, "parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejcia9544502015-08-14 08:24:29 +02006159
Radek Krejcic189a952016-07-11 15:27:07 +02006160 /* insert the node into the schema tree */
6161 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6162 goto error;
6163 }
6164
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006165 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02006166 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006167 if (strcmp(sub->ns->value, LY_NSYIN)) {
6168 /* extension */
6169 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006170 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006171 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006172 c_ref++;
6173 } else if (!strcmp(sub->name, "augment")) {
6174 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006175 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02006176 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006177 } else if (!strcmp(sub->name, "when")) {
6178 if (uses->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006179 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006180 goto error;
6181 }
6182
Radek Krejci5323b492017-01-16 15:40:11 +01006183 uses->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006184 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006185 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006186 goto error;
6187 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006188 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006189 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006190 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006191 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006192 }
6193 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006194
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006195 /* process properties with cardinality 0..n */
6196 if (c_ref) {
6197 uses->refine = calloc(c_ref, sizeof *uses->refine);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006198 LY_CHECK_ERR_GOTO(!uses->refine, LOGMEM, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006199 }
6200 if (c_aug) {
6201 uses->augment = calloc(c_aug, sizeof *uses->augment);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006202 LY_CHECK_ERR_GOTO(!uses->augment, LOGMEM, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006203 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006204 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006205 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006206 LY_CHECK_ERR_GOTO(!uses->iffeature, LOGMEM, error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006207 }
Radek Krejcie534c132016-11-23 13:32:31 +01006208 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01006209 /* some extensions may be already present from the substatements */
6210 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006211 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejcifdc0d702017-01-23 15:58:38 +01006212 retval->ext = reallocated;
6213
6214 /* init memory */
6215 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006216 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006217
Radek Krejcie534c132016-11-23 13:32:31 +01006218 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6219 if (strcmp(sub->ns->value, LY_NSYIN)) {
6220 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006221 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 +01006222 retval->ext_size++;
6223 if (r) {
6224 goto error;
6225 }
6226 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02006227 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006228 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006229 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006230 goto error;
6231 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006232 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006233 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], options, unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006234 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006235 if (r) {
6236 goto error;
6237 }
6238 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006239 r = fill_yin_iffeature(retval, 0, sub, &uses->iffeature[uses->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006240 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006241 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006242 goto error;
6243 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006244 }
6245 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006246
Radek Krejci48464ed2016-03-17 15:44:09 +01006247 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006248 goto error;
6249 }
Radek Krejci74705112015-06-05 10:25:44 +02006250
Michal Vasko508a50d2016-09-07 14:50:33 +02006251 /* check XPath dependencies */
Michal Vasko89afc112017-03-16 13:57:28 +01006252 if (uses->when) {
6253 if (options & LYS_PARSE_OPT_INGRP) {
Michal Vasko364918a2017-03-17 13:23:46 +01006254 if (lyxp_node_check_syntax(retval)) {
Michal Vasko89afc112017-03-16 13:57:28 +01006255 goto error;
6256 }
6257 } else {
6258 if (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1) {
6259 goto error;
6260 }
6261 }
Michal Vasko508a50d2016-09-07 14:50:33 +02006262 }
6263
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006264 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006265
6266error:
6267
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006268 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006269
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006270 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006271}
6272
Michal Vasko0d343d12015-08-24 14:57:36 +02006273/* logs directly
6274 *
6275 * common code for yin_read_module() and yin_read_submodule()
6276 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006277static int
Radek Krejcic071c542016-01-27 14:57:51 +01006278read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
6279 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02006280{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006281 struct ly_ctx *ctx = module->ctx;
Radek Krejci7417a082017-02-16 11:07:59 +01006282 struct lyxml_elem *next, *child, root, grps, augs, revs, exts;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006283 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006284 struct lys_module *trg;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006285 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01006286 int i, r, ret = -1;
Radek Krejcic071c542016-01-27 14:57:51 +01006287 int version_flag = 0;
Michal Vasko5de8a022017-02-08 10:57:26 +01006288 /* (sub)module substatements are ordered in groups, increment this value when moving to another group
6289 * 0 - header-stmts, 1 - linkage-stmts, 2 - meta-stmts, 3 - revision-stmts, 4 - body-stmts */
6290 int substmt_group;
6291 /* just remember last substatement for logging */
6292 const char *substmt_prev;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006293 /* counters */
Radek Krejcie534c132016-11-23 13:32:31 +01006294 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;
6295 int c_ext = 0, c_extinst = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01006296 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006297
Radek Krejcic071c542016-01-27 14:57:51 +01006298 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02006299 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01006300
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006301 /* init */
6302 memset(&root, 0, sizeof root);
6303 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006304 memset(&augs, 0, sizeof augs);
Radek Krejcie534c132016-11-23 13:32:31 +01006305 memset(&exts, 0, sizeof exts);
PavolVican9e81c6a2017-02-09 13:09:07 +01006306 memset(&revs, 0, sizeof revs);
Radek Krejcie0674f82015-06-15 13:58:51 +02006307
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006308 /*
6309 * in the first run, we process elements with cardinality of 1 or 0..1 and
6310 * count elements with cardinality 0..n. Data elements (choices, containers,
6311 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
6312 * need have all top-level and groupings already prepared at that time. In
6313 * the middle loop, we process other elements with carinality of 0..n since
6314 * we need to allocate arrays to store them.
6315 */
Michal Vasko5de8a022017-02-08 10:57:26 +01006316 substmt_group = 0;
6317 substmt_prev = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006318 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01006319 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02006320 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01006321 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006322 continue;
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006323 } else if (strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01006324 /* possible extension instance */
6325 lyxml_unlink_elem(module->ctx, child, 2);
6326 lyxml_add_child(module->ctx, &exts, child);
6327 c_extinst++;
6328 } else if (!submodule && !strcmp(child->name, "namespace")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006329 if (substmt_group > 0) {
6330 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6331 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6332 child->name, substmt_prev);
6333 goto error;
6334 }
6335
PavolVican9e81c6a2017-02-09 13:09:07 +01006336 if (trg->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006337 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006338 goto error;
6339 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006340 GETVAL(value, child, "uri");
PavolVican9e81c6a2017-02-09 13:09:07 +01006341 trg->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006342
Radek Krejci8d6b7422017-02-03 14:42:13 +01006343 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_NAMESPACE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006344 goto error;
6345 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006346 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006347
6348 substmt_prev = "namespace";
Radek Krejcic071c542016-01-27 14:57:51 +01006349 } else if (!submodule && !strcmp(child->name, "prefix")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006350 if (substmt_group > 0) {
6351 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6352 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6353 child->name, substmt_prev);
6354 goto error;
6355 }
6356
PavolVican9e81c6a2017-02-09 13:09:07 +01006357 if (trg->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006358 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006359 goto error;
6360 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006361 GETVAL(value, child, "value");
PavolVican9e81c6a2017-02-09 13:09:07 +01006362 if (lyp_check_identifier(value, LY_IDENT_PREFIX, trg, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006363 goto error;
6364 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006365 trg->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006366
Radek Krejci8d6b7422017-02-03 14:42:13 +01006367 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006368 goto error;
6369 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006370 lyxml_free(ctx, child);
Michal Vasko5de8a022017-02-08 10:57:26 +01006371
6372 substmt_prev = "prefix";
Radek Krejcic071c542016-01-27 14:57:51 +01006373 } else if (submodule && !strcmp(child->name, "belongs-to")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006374 if (substmt_group > 0) {
6375 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6376 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6377 child->name, substmt_prev);
6378 goto error;
6379 }
6380
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006381 if (trg->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006382 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006383 goto error;
6384 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006385 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01006386 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006387 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006388 goto error;
6389 }
Radek Krejcif3886932015-06-04 17:36:06 +02006390
Radek Krejci8d6b7422017-02-03 14:42:13 +01006391 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_BELONGSTO, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006392 goto error;
6393 }
6394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006395 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006396 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006397 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006398 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006399 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006400 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006401 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006402 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006403 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006404 goto error;
6405 }
6406 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006407 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006408 /* check here differs from a generic prefix check, since this prefix
6409 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02006410 */
Radek Krejci48464ed2016-03-17 15:44:09 +01006411 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006412 goto error;
6413 }
Radek Krejcic071c542016-01-27 14:57:51 +01006414 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02006415
Radek Krejci8d6b7422017-02-03 14:42:13 +01006416 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 +01006417 goto error;
6418 }
6419
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006420 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01006421 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02006422
Michal Vasko5de8a022017-02-08 10:57:26 +01006423 substmt_prev = "belongs-to";
6424
Radek Krejcieb00f512015-07-01 16:44:58 +02006425 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006426 } else if (!strcmp(child->name, "import")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006427 if (substmt_group > 1) {
6428 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6429 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6430 child->name, substmt_prev);
6431 goto error;
6432 }
6433 substmt_group = 1;
6434
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006435 c_imp++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006436
6437 substmt_prev = "import";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006438 } else if (!strcmp(child->name, "revision")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006439 if (substmt_group > 3) {
6440 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6441 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6442 child->name, substmt_prev);
6443 goto error;
6444 }
6445 substmt_group = 3;
6446
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006447 c_rev++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006448
PavolVican9e81c6a2017-02-09 13:09:07 +01006449 lyxml_unlink_elem(ctx, child, 2);
6450 lyxml_add_child(ctx, &revs, child);
6451
Michal Vasko5de8a022017-02-08 10:57:26 +01006452 substmt_prev = "revision";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006453 } else if (!strcmp(child->name, "typedef")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006454 substmt_group = 4;
6455
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006456 c_tpdf++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006457
6458 substmt_prev = "typedef";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006459 } else if (!strcmp(child->name, "identity")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006460 substmt_group = 4;
6461
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006462 c_ident++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006463
6464 substmt_prev = "identity";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006465 } else if (!strcmp(child->name, "include")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006466 if (substmt_group > 1) {
6467 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6468 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6469 child->name, substmt_prev);
6470 goto error;
6471 }
6472 substmt_group = 1;
6473
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006474 c_inc++;
Michal Vasko5de8a022017-02-08 10:57:26 +01006475
6476 substmt_prev = "include";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006477 } else if (!strcmp(child->name, "augment")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006478 substmt_group = 4;
6479
Radek Krejcif5be10f2015-06-16 13:29:36 +02006480 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006481 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01006482 lyxml_unlink_elem(ctx, child, 2);
6483 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006484
Michal Vasko5de8a022017-02-08 10:57:26 +01006485 substmt_prev = "augment";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006486 } else if (!strcmp(child->name, "feature")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006487 substmt_group = 4;
6488
Radek Krejci3cf9e222015-06-18 11:37:50 +02006489 c_ftrs++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006490
Michal Vasko5de8a022017-02-08 10:57:26 +01006491 substmt_prev = "feature";
Michal Vasko5de8a022017-02-08 10:57:26 +01006492
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006493 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006494 } else if (!strcmp(child->name, "container") ||
6495 !strcmp(child->name, "leaf-list") ||
6496 !strcmp(child->name, "leaf") ||
6497 !strcmp(child->name, "list") ||
6498 !strcmp(child->name, "choice") ||
6499 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006500 !strcmp(child->name, "anyxml") ||
Radek Krejcif95b6292017-02-13 15:57:37 +01006501 !strcmp(child->name, "anydata") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006502 !strcmp(child->name, "rpc") ||
6503 !strcmp(child->name, "notification")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006504 substmt_group = 4;
6505
Radek Krejcic071c542016-01-27 14:57:51 +01006506 lyxml_unlink_elem(ctx, child, 2);
6507 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006508
Michal Vasko5de8a022017-02-08 10:57:26 +01006509 substmt_prev = "data definition";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006510 } else if (!strcmp(child->name, "grouping")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006511 substmt_group = 4;
6512
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006513 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01006514 lyxml_unlink_elem(ctx, child, 2);
6515 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006516
Michal Vasko5de8a022017-02-08 10:57:26 +01006517 substmt_prev = "grouping";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006518 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006519 } else if (!strcmp(child->name, "description")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006520 if (substmt_group > 2) {
6521 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6522 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6523 child->name, substmt_prev);
6524 goto error;
6525 }
6526 substmt_group = 2;
6527
Radek Krejcic071c542016-01-27 14:57:51 +01006528 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006529 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006530 goto error;
6531 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006532 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006533 goto error;
6534 }
Radek Krejcic071c542016-01-27 14:57:51 +01006535 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006536 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006537 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006538 goto error;
6539 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006540
6541 substmt_prev = "description";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006542 } else if (!strcmp(child->name, "reference")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006543 if (substmt_group > 2) {
6544 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6545 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6546 child->name, substmt_prev);
6547 goto error;
6548 }
6549 substmt_group = 2;
6550
Radek Krejcic071c542016-01-27 14:57:51 +01006551 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006552 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006553 goto error;
6554 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006555 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006556 goto error;
6557 }
Radek Krejcic071c542016-01-27 14:57:51 +01006558 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006559 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006560 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006561 goto error;
6562 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006563
6564 substmt_prev = "reference";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006565 } else if (!strcmp(child->name, "organization")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006566 if (substmt_group > 2) {
6567 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6568 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6569 child->name, substmt_prev);
6570 goto error;
6571 }
6572 substmt_group = 2;
6573
Radek Krejcic071c542016-01-27 14:57:51 +01006574 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006575 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006576 goto error;
6577 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006578 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_ORGANIZATION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006579 goto error;
6580 }
Radek Krejcic071c542016-01-27 14:57:51 +01006581 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006582 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006583 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006584 goto error;
6585 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006586
6587 substmt_prev = "organization";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006588 } else if (!strcmp(child->name, "contact")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006589 if (substmt_group > 2) {
6590 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6591 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6592 child->name, substmt_prev);
6593 goto error;
6594 }
6595 substmt_group = 2;
6596
Radek Krejcic071c542016-01-27 14:57:51 +01006597 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006598 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006599 goto error;
6600 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01006601 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_CONTACT, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006602 goto error;
6603 }
Radek Krejcic071c542016-01-27 14:57:51 +01006604 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006605 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006606 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006607 goto error;
6608 }
Michal Vasko5de8a022017-02-08 10:57:26 +01006609
6610 substmt_prev = "contact";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006611 } else if (!strcmp(child->name, "yang-version")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006612 if (substmt_group > 0) {
6613 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
6614 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Statement \"%s\" cannot appear after \"%s\" statement.",
6615 child->name, substmt_prev);
6616 goto error;
6617 }
6618
Radek Krejcic071c542016-01-27 14:57:51 +01006619 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006620 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006621 goto error;
6622 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006623 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02006624 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006625 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006626 goto error;
6627 }
Radek Krejcic071c542016-01-27 14:57:51 +01006628 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006629 if (!strcmp(value, "1")) {
6630 if (submodule) {
6631 if (module->version > 1) {
6632 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6633 goto error;
6634 }
Radek Krejci29eac3d2017-06-01 16:50:02 +02006635 submodule->version = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006636 } else {
6637 module->version = 1;
6638 }
6639 } else {
6640 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006641 if (module->version < 2) {
Michal Vasko88de3e42016-06-29 11:05:32 +02006642 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6643 goto error;
6644 }
Radek Krejci29eac3d2017-06-01 16:50:02 +02006645 submodule->version = 2;
Michal Vasko88de3e42016-06-29 11:05:32 +02006646 } else {
6647 module->version = 2;
6648 }
6649 }
6650
Radek Krejci8d6b7422017-02-03 14:42:13 +01006651 if (lyp_yin_parse_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_VERSION, 0, unres)) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006652 goto error;
6653 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006654 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006655
Michal Vasko5de8a022017-02-08 10:57:26 +01006656 substmt_prev = "yang-version";
Radek Krejci1d82ef62015-08-07 14:44:40 +02006657 } else if (!strcmp(child->name, "extension")) {
Michal Vasko5de8a022017-02-08 10:57:26 +01006658 substmt_group = 4;
6659
Radek Krejcia1a6b762016-11-14 09:53:38 +09006660 c_ext++;
Radek Krejci5166a892015-07-02 16:44:24 +02006661
Michal Vasko5de8a022017-02-08 10:57:26 +01006662 substmt_prev = "extension";
Radek Krejcia1a6b762016-11-14 09:53:38 +09006663 } else if (!strcmp(child->name, "deviation")) {
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006664 substmt_group = 4;
6665
Radek Krejcia1a6b762016-11-14 09:53:38 +09006666 c_dev++;
6667
Michal Vaskoe8c73dd2017-02-10 11:34:17 +01006668 substmt_prev = "deviation";
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006669 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01006670 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006671 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006672 }
6673 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006674
Radek Krejcic071c542016-01-27 14:57:51 +01006675 /* check for mandatory statements */
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006676 if (submodule) {
6677 if (!submodule->prefix) {
6678 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
6679 goto error;
6680 }
6681 if (!version_flag) {
6682 /* check version compatibility with the main module */
6683 if (module->version > 1) {
6684 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6685 goto error;
6686 }
6687 }
6688 } else {
PavolVican9e81c6a2017-02-09 13:09:07 +01006689 if (!trg->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006690 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006691 goto error;
6692 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006693 if (!trg->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006694 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006695 goto error;
6696 }
6697 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02006698
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006699 /* allocate arrays for elements with cardinality of 0..n */
6700 if (c_imp) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006701 trg->imp = calloc(c_imp, sizeof *trg->imp);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006702 LY_CHECK_ERR_GOTO(!trg->imp, LOGMEM, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006703 }
6704 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006705 trg->rev = calloc(c_rev, sizeof *trg->rev);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006706 LY_CHECK_ERR_GOTO(!trg->rev, LOGMEM, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006707 }
6708 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01006709 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006710 LY_CHECK_ERR_GOTO(!trg->tpdf, LOGMEM, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006711 }
6712 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01006713 trg->ident = calloc(c_ident, sizeof *trg->ident);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006714 LY_CHECK_ERR_GOTO(!trg->ident, LOGMEM, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006715 }
6716 if (c_inc) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006717 trg->inc = calloc(c_inc, sizeof *trg->inc);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006718 LY_CHECK_ERR_GOTO(!trg->inc, LOGMEM, error);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006719 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006720 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01006721 trg->augment = calloc(c_aug, sizeof *trg->augment);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006722 LY_CHECK_ERR_GOTO(!trg->augment, LOGMEM, error);
Radek Krejcif5be10f2015-06-16 13:29:36 +02006723 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006724 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01006725 trg->features = calloc(c_ftrs, sizeof *trg->features);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006726 LY_CHECK_ERR_GOTO(!trg->features, LOGMEM, error);
Radek Krejci3cf9e222015-06-18 11:37:50 +02006727 }
Radek Krejcieb00f512015-07-01 16:44:58 +02006728 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006729 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006730 LY_CHECK_ERR_GOTO(!trg->deviation, LOGMEM, error);
Radek Krejcieb00f512015-07-01 16:44:58 +02006731 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09006732 if (c_ext) {
6733 trg->extensions = calloc(c_ext, sizeof *trg->extensions);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006734 LY_CHECK_ERR_GOTO(!trg->extensions, LOGMEM, error);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006735 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006736
PavolVican9e81c6a2017-02-09 13:09:07 +01006737 /* middle part 1 - process revision and then check whether this (sub)module was not already parsed, add it there */
6738 LY_TREE_FOR_SAFE(revs.child, next, child) {
Radek Krejci7417a082017-02-16 11:07:59 +01006739 r = fill_yin_revision(trg, child, &trg->rev[trg->rev_size], unres);
6740 trg->rev_size++;
6741 if (r) {
PavolVican9e81c6a2017-02-09 13:09:07 +01006742 goto error;
6743 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006744
Radek Krejci7417a082017-02-16 11:07:59 +01006745 /* check uniqueness of the revision date - not required by RFC */
6746 for (i = 0; i < (trg->rev_size - 1); i++) {
6747 if (!strcmp(trg->rev[i].date, trg->rev[trg->rev_size - 1].date)) {
6748 LOGWRN("Module's revisions are not unique (%s).", trg->rev[trg->rev_size - 1].date);
6749 break;
PavolVican9e81c6a2017-02-09 13:09:07 +01006750 }
6751 }
PavolVican9e81c6a2017-02-09 13:09:07 +01006752
6753 lyxml_free(ctx, child);
6754 }
6755
6756 /* check the module with respect to the context now */
6757 if (!submodule) {
6758 switch (lyp_ctx_check_module(module)) {
6759 case -1:
6760 goto error;
6761 case 0:
6762 break;
6763 case 1:
6764 /* it's already there */
6765 ret = 1;
6766 goto error;
6767 }
6768 }
6769
6770 /* middle part 2 - process nodes with cardinality of 0..n except the data nodes and augments */
Michal Vasko2f7925f2015-10-21 15:06:56 +02006771 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02006772 if (!strcmp(child->name, "import")) {
Radek Krejcie534c132016-11-23 13:32:31 +01006773 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size], unres);
Radek Krejcic071c542016-01-27 14:57:51 +01006774 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006775 if (r) {
6776 goto error;
6777 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006778
Radek Krejci1d82ef62015-08-07 14:44:40 +02006779 } else if (!strcmp(child->name, "include")) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006780 r = fill_yin_include(module, submodule, child, &trg->inc[trg->inc_size], unres);
6781 trg->inc_size++;
6782 if (r) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006783 goto error;
6784 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006785
Radek Krejci1d82ef62015-08-07 14:44:40 +02006786 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006787 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
6788 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006789 if (r) {
6790 goto error;
6791 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006792
Radek Krejci1d82ef62015-08-07 14:44:40 +02006793 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006794 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
6795 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006796 if (r) {
6797 goto error;
6798 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006799
Radek Krejci1d82ef62015-08-07 14:44:40 +02006800 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006801 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
6802 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006803 if (r) {
6804 goto error;
6805 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006806
Radek Krejcia1a6b762016-11-14 09:53:38 +09006807 } else if (!strcmp(child->name, "extension")) {
Radek Krejcie534c132016-11-23 13:32:31 +01006808 r = fill_yin_extension(trg, child, &trg->extensions[trg->extensions_size], unres);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006809 trg->extensions_size++;
6810 if (r) {
6811 goto error;
6812 }
6813
Radek Krejci1d82ef62015-08-07 14:44:40 +02006814 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006815 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
6816 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02006817 if (r) {
6818 goto error;
6819 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006820 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006821 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006822
Radek Krejcie534c132016-11-23 13:32:31 +01006823 /* process extension instances */
Radek Krejci8ee94802017-02-10 12:38:40 +01006824 if (c_extinst) {
6825 /* some extensions may be already present from the substatements */
6826 reallocated = realloc(trg->ext, (c_extinst + trg->ext_size) * sizeof *trg->ext);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006827 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error);
Radek Krejci8ee94802017-02-10 12:38:40 +01006828 trg->ext = reallocated;
6829
6830 /* init memory */
6831 memset(&trg->ext[trg->ext_size], 0, c_extinst * sizeof *trg->ext);
6832
6833 LY_TREE_FOR_SAFE(exts.child, next, child) {
6834 r = lyp_yin_fill_ext(trg, LYEXT_PAR_MODULE, 0, 0, trg, child, &trg->ext, trg->ext_size, unres);
6835 trg->ext_size++;
6836 if (r) {
6837 goto error;
6838 }
6839 }
Radek Krejcie534c132016-11-23 13:32:31 +01006840 }
6841
Radek Krejcif5be10f2015-06-16 13:29:36 +02006842 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01006843 * refer to them. Submodule's data nodes are stored in the
6844 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006845 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006846 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006847 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006848 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006849 goto error;
6850 }
Radek Krejci74705112015-06-05 10:25:44 +02006851
Michal Vasko345da0a2015-12-02 10:35:55 +01006852 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006853 }
Radek Krejci74705112015-06-05 10:25:44 +02006854
Radek Krejcif5be10f2015-06-16 13:29:36 +02006855 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006856 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02006857
Radek Krejci1d82ef62015-08-07 14:44:40 +02006858 if (!strcmp(child->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006859 node = read_yin_container(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006860 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006861 node = read_yin_leaflist(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006862 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006863 node = read_yin_leaf(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006864 } else if (!strcmp(child->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006865 node = read_yin_list(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006866 } else if (!strcmp(child->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006867 node = read_yin_choice(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006868 } else if (!strcmp(child->name, "uses")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006869 node = read_yin_uses(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006870 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006871 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02006872 } else if (!strcmp(child->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006873 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006874 } else if (!strcmp(child->name, "rpc")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006875 node = read_yin_rpc_action(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006876 } else if (!strcmp(child->name, "notification")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006877 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006878 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006879 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006880 goto error;
6881 }
Radek Krejci25d782a2015-05-22 15:03:23 +02006882
Michal Vasko345da0a2015-12-02 10:35:55 +01006883 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006884 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006885
Michal Vasko2f7925f2015-10-21 15:06:56 +02006886 /* ... and finally augments (last, so we can augment our data, for instance) */
6887 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01006888 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], 0, unres);
Radek Krejcic071c542016-01-27 14:57:51 +01006889 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02006890
Michal Vasko2f7925f2015-10-21 15:06:56 +02006891 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02006892 goto error;
6893 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006894 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02006895 }
6896
PavolVican9e81c6a2017-02-09 13:09:07 +01006897 return 0;
Radek Krejciefaeba32015-05-27 14:30:57 +02006898
6899error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006900 while (root.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01006901 lyxml_free(ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006902 }
6903 while (grps.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01006904 lyxml_free(ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006905 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006906 while (augs.child) {
PavolVican9e81c6a2017-02-09 13:09:07 +01006907 lyxml_free(ctx, augs.child);
6908 }
6909 while (revs.child) {
6910 lyxml_free(ctx, revs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006911 }
Radek Krejcie534c132016-11-23 13:32:31 +01006912 while (exts.child) {
6913 lyxml_free(module->ctx, exts.child);
6914 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006915
PavolVican9e81c6a2017-02-09 13:09:07 +01006916 return ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02006917}
6918
Michal Vasko0d343d12015-08-24 14:57:36 +02006919/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01006920struct lys_submodule *
6921yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02006922{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006923 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01006924 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006925 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02006926
Michal Vasko5a721fd2016-02-16 12:16:48 +01006927 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02006928
Radek Krejcie1bacd72017-03-01 13:18:46 +01006929 yin = lyxml_parse_mem(module->ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006930 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01006931 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006932 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006933
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006934 /* check root element */
6935 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006936 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006937 goto error;
6938 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006939
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006940 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01006941 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006942 goto error;
6943 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006944
Michal Vasko5a721fd2016-02-16 12:16:48 +01006945 submodule = calloc(1, sizeof *submodule);
Radek Krejcia8d111f2017-05-31 13:57:37 +02006946 LY_CHECK_ERR_GOTO(!submodule, LOGMEM, error);
Radek Krejciefaeba32015-05-27 14:30:57 +02006947
Michal Vasko5a721fd2016-02-16 12:16:48 +01006948 submodule->ctx = module->ctx;
6949 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
6950 submodule->type = 1;
Radek Krejci29eac3d2017-06-01 16:50:02 +02006951 submodule->implemented = module->implemented;
Michal Vasko5a721fd2016-02-16 12:16:48 +01006952 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02006953
Radek Krejci9e757e02017-03-08 17:18:09 +01006954 /* add into the list of processed modules */
6955 if (lyp_check_circmod_add((struct lys_module *)submodule)) {
6956 goto error;
6957 }
6958
Michal Vasko5a721fd2016-02-16 12:16:48 +01006959 LOGVRB("Reading submodule \"%s\".", submodule->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01006960 /* module cannot be changed in this case and 1 cannot be returned */
Michal Vasko5a721fd2016-02-16 12:16:48 +01006961 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006962 goto error;
6963 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006964
Radek Krejci33fc4772017-01-26 16:00:35 +01006965 lyp_sort_revisions((struct lys_module *)submodule);
6966
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006967 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01006968 lyxml_free(module->ctx, yin);
Radek Krejci9e757e02017-03-08 17:18:09 +01006969 lyp_check_circmod_pop(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02006970
Michal Vasko5a721fd2016-02-16 12:16:48 +01006971 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006972 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02006973
6974error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006975 /* cleanup */
Michal Vasko44ab1462017-05-18 13:18:36 +02006976 unres_schema_free((struct lys_module *)submodule, &unres, 0);
Michal Vasko345da0a2015-12-02 10:35:55 +01006977 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01006978
Michal Vasko5a721fd2016-02-16 12:16:48 +01006979 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01006980 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01006981 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01006982 }
6983
Michal Vasko5a721fd2016-02-16 12:16:48 +01006984 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01006985
Radek Krejci9e757e02017-03-08 17:18:09 +01006986 lyp_check_circmod_pop(module->ctx);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006987 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
6988 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006989 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006990 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02006991}
6992
Michal Vasko0d343d12015-08-24 14:57:36 +02006993/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02006994struct lys_module *
Radek Krejci37f9ba32017-02-10 16:50:35 +01006995yin_read_module_(struct ly_ctx *ctx, struct lyxml_elem *yin, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02006996{
Pavol Vicanc99b59e2016-03-22 15:46:39 +01006997 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006998 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006999 const char *value;
PavolVican9e81c6a2017-02-09 13:09:07 +01007000 int ret;
Radek Krejciefaeba32015-05-27 14:30:57 +02007001
Radek Krejcic071c542016-01-27 14:57:51 +01007002 unres = calloc(1, sizeof *unres);
Radek Krejcia8d111f2017-05-31 13:57:37 +02007003 LY_CHECK_ERR_RETURN(!unres, LOGMEM, NULL);
Radek Krejcic071c542016-01-27 14:57:51 +01007004
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007005 /* check root element */
7006 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci9a909bd2016-10-24 15:45:51 +02007007 if (ly_strequal("submodule", yin->name, 0)) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007008 LOGVAL(LYE_SUBMODULE, LY_VLOG_NONE, NULL);
7009 } else {
7010 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci9a909bd2016-10-24 15:45:51 +02007011 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007012 goto error;
7013 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007014
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007015 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01007016 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007017 goto error;
7018 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007019
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007020 module = calloc(1, sizeof *module);
Radek Krejcia8d111f2017-05-31 13:57:37 +02007021 LY_CHECK_ERR_GOTO(!module, LOGMEM, error);
Radek Krejciefaeba32015-05-27 14:30:57 +02007022
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007023 module->ctx = ctx;
7024 module->name = lydict_insert(ctx, value, strlen(value));
7025 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02007026 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02007027
Radek Krejci9e757e02017-03-08 17:18:09 +01007028 /* add into the list of processed modules */
7029 if (lyp_check_circmod_add(module)) {
7030 goto error;
7031 }
7032
Michal Vasko9f258e42016-02-11 11:36:27 +01007033 LOGVRB("Reading module \"%s\".", module->name);
PavolVican9e81c6a2017-02-09 13:09:07 +01007034 ret = read_sub_module(module, NULL, yin, unres);
7035 if (ret == -1) {
Radek Krejcic071c542016-01-27 14:57:51 +01007036 goto error;
7037 }
7038
PavolVican9e81c6a2017-02-09 13:09:07 +01007039 if (ret == 1) {
7040 assert(!unres->count);
7041 } else {
7042 /* resolve rest of unres items */
7043 if (unres->count && resolve_unres_schema(module, unres)) {
7044 goto error;
7045 }
7046
7047 /* check correctness of includes */
7048 if (lyp_check_include_missing(module)) {
7049 goto error;
7050 }
Michal Vasko7b460e52017-02-10 14:50:26 +01007051
7052 /* remove our submodules from the parsed submodules list */
7053 lyp_del_includedup(module);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007054 }
Radek Krejciefaeba32015-05-27 14:30:57 +02007055
Radek Krejci95f22ae2017-01-20 14:25:53 +01007056 lyp_sort_revisions(module);
Radek Krejci6bd2c022017-02-01 15:04:49 +01007057
7058 if (lyp_rfn_apply_ext(module) || lyp_deviation_apply_ext(module)) {
7059 goto error;
7060 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01007061
Radek Krejciff4874d2016-03-07 12:30:50 +01007062 if (revision) {
7063 /* check revision of the parsed model */
7064 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01007065 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
7066 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01007067 goto error;
7068 }
7069 }
7070
PavolVican9e81c6a2017-02-09 13:09:07 +01007071 /* add into context if not already there */
7072 if (!ret) {
7073 if (module->deviation_size && !module->implemented) {
7074 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
7075 /* deviations always causes target to be made implemented,
7076 * but augents and leafrefs not, so we have to apply them now */
7077 if (lys_set_implemented(module)) {
7078 goto error;
7079 }
7080 }
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01007081
PavolVican9e81c6a2017-02-09 13:09:07 +01007082 if (lyp_ctx_add_module(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02007083 goto error;
7084 }
PavolVican9e81c6a2017-02-09 13:09:07 +01007085 } else {
7086 /* free what was parsed */
7087 lys_free(module, NULL, 0);
7088
7089 /* get the model from the context */
Radek Krejcidfb00d62017-09-06 09:39:35 +02007090 module = (struct lys_module *)ly_ctx_get_module(ctx, value, revision, 0);
PavolVican9e81c6a2017-02-09 13:09:07 +01007091 assert(module);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007092 }
7093
Michal Vasko44ab1462017-05-18 13:18:36 +02007094 unres_schema_free(NULL, &unres, 0);
Radek Krejci9e757e02017-03-08 17:18:09 +01007095 lyp_check_circmod_pop(ctx);
Michal Vasko9f258e42016-02-11 11:36:27 +01007096 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007097 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007098
7099error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007100 /* cleanup */
Michal Vasko44ab1462017-05-18 13:18:36 +02007101 unres_schema_free(module, &unres, 1);
Radek Krejcib8c07b82016-02-12 11:11:55 +01007102
7103 if (!module) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01007104 if (ly_vecode != LYVE_SUBMODULE) {
7105 LOGERR(ly_errno, "Module parsing failed.");
7106 }
Radek Krejcib8c07b82016-02-12 11:11:55 +01007107 return NULL;
7108 }
7109
7110 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02007111
Radek Krejci9e757e02017-03-08 17:18:09 +01007112 lyp_check_circmod_pop(ctx);
Michal Vaskocf0489e2017-02-13 11:57:45 +01007113 lyp_del_includedup(module);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02007114 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01007115 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02007116 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02007117}
Radek Krejci8d6b7422017-02-03 14:42:13 +01007118
Radek Krejci37f9ba32017-02-10 16:50:35 +01007119/* logs directly */
7120struct lys_module *
7121yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
7122{
7123 struct lyxml_elem *yin;
7124 struct lys_module *result;
7125
Radek Krejcie1bacd72017-03-01 13:18:46 +01007126 yin = lyxml_parse_mem(ctx, data, LYXML_PARSE_NOMIXEDCONTENT);
Radek Krejci37f9ba32017-02-10 16:50:35 +01007127 if (!yin) {
7128 LOGERR(ly_errno, "Module parsing failed.");
7129 return NULL;
7130 }
7131
7132 result = yin_read_module_(ctx, yin, revision, implement);
7133
7134 lyxml_free(ctx, yin);
7135
7136 return result;
7137}
7138
Radek Krejcic1885952017-02-07 09:37:51 +01007139static int
7140yin_parse_extcomplex_bool(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007141 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007142 const char *true_val, const char *false_val, struct unres_schema *unres)
7143{
7144 uint8_t *val;
7145 const char *str;
7146 struct lyext_substmt *info;
7147
7148 val = lys_ext_complex_get_substmt(stmt, ext, &info);
7149 if (!val) {
7150 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7151 return EXIT_FAILURE;
7152 }
7153 if (*val) {
7154 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7155 return EXIT_FAILURE;
7156 }
7157
Radek Krejcidb35f172017-02-27 11:03:01 +01007158 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007159 return EXIT_FAILURE;
7160 }
7161
7162 str = lyxml_get_attr(node, "value", NULL);
7163 if (!str) {
7164 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
7165 } else if (true_val && !strcmp(true_val, str)) {
7166 /* true value */
7167 *val = 1;
7168 } else if (false_val && !strcmp(false_val, str)) {
7169 /* false value */
7170 *val = 2;
7171 } else {
7172 /* unknown value */
7173 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
7174 return EXIT_FAILURE;
7175 }
7176
7177 return EXIT_SUCCESS;
7178}
7179
Radek Krejci8d6b7422017-02-03 14:42:13 +01007180/*
7181 * argelem - 1 if the value is stored in a standalone YIN element, 0 if stored as attribute
7182 * argname - name of the element/attribute where the value is stored
7183 */
7184static int
7185yin_parse_extcomplex_str(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007186 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejci8d6b7422017-02-03 14:42:13 +01007187 int argelem, const char *argname, struct unres_schema *unres)
7188{
7189 int c;
PavolVican99c70722017-02-18 17:25:52 +01007190 const char **str, ***p = NULL, *value;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007191 void *reallocated;
7192 struct lyext_substmt *info;
7193
7194 str = lys_ext_complex_get_substmt(stmt, ext, &info);
7195 if (!str) {
7196 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7197 return EXIT_FAILURE;
7198 }
7199 if (info->cardinality < LY_STMT_CARD_SOME && *str) {
7200 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7201 return EXIT_FAILURE;
7202 }
7203
7204 c = 0;
7205 if (info->cardinality >= LY_STMT_CARD_SOME) {
7206 /* there can be multiple instances, str is actually const char *** */
7207 p = (const char ***)str;
Radek Krejci56c80412017-02-09 10:44:16 +01007208 if (!p[0]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007209 /* allocate initial array */
Radek Krejci56c80412017-02-09 10:44:16 +01007210 p[0] = malloc(2 * sizeof(const char *));
Radek Krejcia8d111f2017-05-31 13:57:37 +02007211 LY_CHECK_ERR_RETURN(!p[0], LOGMEM, EXIT_FAILURE);
Radek Krejci56c80412017-02-09 10:44:16 +01007212 if (stmt == LY_STMT_BELONGSTO) {
7213 /* allocate another array for the belongs-to's prefixes */
7214 p[1] = malloc(2 * sizeof(const char *));
Radek Krejcia8d111f2017-05-31 13:57:37 +02007215 LY_CHECK_ERR_RETURN(!p[1], LOGMEM, EXIT_FAILURE);
PavolVican99c70722017-02-18 17:25:52 +01007216 } else if (stmt == LY_STMT_ARGUMENT) {
7217 /* allocate another array for the yin element */
PavolVican4b80d042017-02-23 14:30:27 +01007218 ((uint8_t **)p)[1] = malloc(2 * sizeof(uint8_t));
Radek Krejcia8d111f2017-05-31 13:57:37 +02007219 LY_CHECK_ERR_RETURN(!p[1], LOGMEM, EXIT_FAILURE);
Radek Krejci56c80412017-02-09 10:44:16 +01007220 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007221 } else {
Radek Krejci56c80412017-02-09 10:44:16 +01007222 /* get the index in the array to add new item */
7223 for (c = 0; p[0][c]; c++);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007224 }
Radek Krejci56c80412017-02-09 10:44:16 +01007225 str = p[0];
Radek Krejci8d6b7422017-02-03 14:42:13 +01007226 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007227 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, c, unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007228 return EXIT_FAILURE;
7229 }
7230
7231 if (argelem) {
Radek Krejci56c80412017-02-09 10:44:16 +01007232 str[c] = read_yin_subnode(mod->ctx, node, argname);
7233 if (!str[c]) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007234 return EXIT_FAILURE;
7235 }
Radek Krejci56c80412017-02-09 10:44:16 +01007236 } else {
7237 str[c] = lyxml_get_attr(node, argname, NULL);
7238 if (!str[c]) {
7239 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, argname, node->name);
7240 return EXIT_FAILURE;
7241 } else {
7242 str[c] = lydict_insert(mod->ctx, str[c], 0);
7243 }
7244
7245 if (stmt == LY_STMT_BELONGSTO) {
7246 /* get the belongs-to's mandatory prefix substatement */
7247 if (!node->child) {
7248 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", node->name);
7249 return EXIT_FAILURE;
7250 } else if (strcmp(node->child->name, "prefix")) {
7251 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
7252 return EXIT_FAILURE;
7253 } else if (node->child->next) {
7254 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
7255 return EXIT_FAILURE;
7256 }
7257 /* and now finally get the value */
7258 if (p) {
7259 str = p[1];
7260 } else {
7261 str++;
7262 }
7263 str[c] = lyxml_get_attr(node->child, "value", ((void *)0));
7264 if (!str[c]) {
7265 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
7266 return EXIT_FAILURE;
7267 }
7268 str[c] = lydict_insert(mod->ctx, str[c], 0);
7269
PavolVican6d400872017-03-01 15:19:18 +01007270 if (!str[c] || lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node->child, LYEXT_SUBSTMT_PREFIX, c, unres)) {
Radek Krejci56c80412017-02-09 10:44:16 +01007271 return EXIT_FAILURE;
7272 }
PavolVican99c70722017-02-18 17:25:52 +01007273 } else if (stmt == LY_STMT_ARGUMENT) {
7274 str = (p) ? p[1] : str + 1;
7275 if (!node->child) {
7276 /* default value of yin element */
7277 ((uint8_t *)str)[c] = 2;
7278 } else {
7279 /* get optional yin-element substatement */
7280 if (strcmp(node->child->name, "yin-element")) {
7281 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->name);
7282 return EXIT_FAILURE;
7283 } else if (node->child->next) {
7284 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->child->next->name);
7285 return EXIT_FAILURE;
7286 } else {
7287 /* and now finally get the value */
7288 value = lyxml_get_attr(node->child, "value", NULL);
7289 if (!value) {
7290 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->child->name);
7291 return EXIT_FAILURE;
7292 }
7293 if (ly_strequal(value, "true", 0)) {
7294 ((uint8_t *)str)[c] = 1;
7295 } else if (ly_strequal(value, "false", 0)) {
7296 ((uint8_t *)str)[c] = 2;
7297 } else {
7298 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
7299 return EXIT_FAILURE;
7300 }
7301
7302 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node->child, LYEXT_SUBSTMT_YINELEM, c, unres)) {
7303 return EXIT_FAILURE;
7304 }
7305 }
7306 }
Radek Krejci56c80412017-02-09 10:44:16 +01007307 }
7308 }
7309 if (p) {
7310 /* enlarge the array(s) */
7311 reallocated = realloc(p[0], (c + 2) * sizeof(const char *));
7312 if (!reallocated) {
7313 LOGMEM;
7314 lydict_remove(mod->ctx, p[0][c]);
7315 p[0][c] = NULL;
7316 return EXIT_FAILURE;
7317 }
7318 p[0] = reallocated;
7319 p[0][c + 1] = NULL;
7320
7321 if (stmt == LY_STMT_BELONGSTO) {
7322 /* enlarge the second belongs-to's array with prefixes */
7323 reallocated = realloc(p[1], (c + 2) * sizeof(const char *));
7324 if (!reallocated) {
7325 LOGMEM;
7326 lydict_remove(mod->ctx, p[1][c]);
7327 p[1][c] = NULL;
7328 return EXIT_FAILURE;
7329 }
7330 p[1] = reallocated;
7331 p[1][c + 1] = NULL;
PavolVican99c70722017-02-18 17:25:52 +01007332 } else if (stmt == LY_STMT_ARGUMENT){
7333 /* enlarge the second argument's array with yin element */
7334 reallocated = realloc(p[1], (c + 2) * sizeof(uint8_t));
7335 if (!reallocated) {
7336 LOGMEM;
7337 ((uint8_t *)p[1])[c] = 0;
7338 return EXIT_FAILURE;
7339 }
7340 p[1] = reallocated;
7341 ((uint8_t *)p[1])[c + 1] = 0;
Radek Krejci56c80412017-02-09 10:44:16 +01007342 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007343 }
7344
7345 return EXIT_SUCCESS;
7346}
7347
7348static void *
7349yin_getplace_for_extcomplex_flags(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt,
7350 uint16_t mask)
7351{
7352 void *data;
7353 struct lyext_substmt *info;
7354
7355 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7356 if (!data) {
7357 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7358 return NULL;
7359 }
7360 if (info->cardinality < LY_STMT_CARD_SOME && ((*(uint16_t *)data) & mask)) {
7361 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7362 return NULL;
7363 }
7364
7365 return data;
7366}
7367
Radek Krejcic1885952017-02-07 09:37:51 +01007368static int
7369yin_parse_extcomplex_flag(struct lys_module *mod, struct lyxml_elem *node,
Radek Krejcibe336392017-02-07 10:54:24 +01007370 struct lys_ext_instance_complex *ext, LY_STMT stmt,
Radek Krejcic1885952017-02-07 09:37:51 +01007371 const char *val1_str, const char *val2_str, uint16_t mask,
7372 uint16_t val1, uint16_t val2, struct unres_schema *unres)
7373{
7374 uint16_t *val;
7375 const char *str;
7376
7377 val = yin_getplace_for_extcomplex_flags(node, ext, stmt, mask);
7378 if (!val) {
7379 return EXIT_FAILURE;
7380 }
7381
7382 str = lyxml_get_attr(node, "value", NULL);
7383 if (!str) {
7384 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, "value", node->name);
7385 } else if (!strcmp(val1_str, str)) {
7386 *val = *val | val1;
7387 } else if (!strcmp(val2_str, str)) {
7388 *val = *val | val2;
7389 } else {
7390 /* unknown value */
7391 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, str, node->name);
7392 return EXIT_FAILURE;
7393 }
Radek Krejcidb35f172017-02-27 11:03:01 +01007394 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, (LYEXT_SUBSTMT)stmt, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007395 return EXIT_FAILURE;
7396 }
7397 return EXIT_SUCCESS;
7398}
7399
Radek Krejcif95b6292017-02-13 15:57:37 +01007400static struct lys_node **
7401yin_getplace_for_extcomplex_node(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7402{
7403 struct lyext_substmt *info;
7404 struct lys_node **snode, *siter;
7405
7406 snode = lys_ext_complex_get_substmt(stmt, ext, &info);
7407 if (!snode) {
7408 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7409 return NULL;
7410 }
7411 if (info->cardinality < LY_STMT_CARD_SOME) {
7412 LY_TREE_FOR(*snode, siter) {
7413 if (stmt == lys_snode2stmt(siter->nodetype)) {
7414 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7415 return NULL;
7416 }
7417 }
7418 }
7419
7420 return snode;
7421}
7422
Radek Krejci8d6b7422017-02-03 14:42:13 +01007423static void **
7424yin_getplace_for_extcomplex_struct(struct lyxml_elem *node, struct lys_ext_instance_complex *ext, LY_STMT stmt)
7425{
7426 int c;
7427 void **data, ***p = NULL;
7428 void *reallocated;
7429 struct lyext_substmt *info;
7430
7431 data = lys_ext_complex_get_substmt(stmt, ext, &info);
7432 if (!data) {
7433 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7434 return NULL;
7435 }
7436 if (info->cardinality < LY_STMT_CARD_SOME && *data) {
7437 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name);
7438 return NULL;
7439 }
7440
7441 c = 0;
7442 if (info->cardinality >= LY_STMT_CARD_SOME) {
7443 /* there can be multiple instances, so instead of pointer to array,
7444 * we have in data pointer to pointer to array */
7445 p = (void ***)data;
7446 data = *p;
7447 if (!data) {
7448 /* allocate initial array */
7449 *p = data = malloc(2 * sizeof(void *));
Radek Krejcia8d111f2017-05-31 13:57:37 +02007450 LY_CHECK_ERR_RETURN(!data, LOGMEM, NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007451 } else {
7452 for (c = 0; *data; data++, c++);
7453 }
7454 }
7455
7456 if (p) {
7457 /* enlarge the array */
7458 reallocated = realloc(*p, (c + 2) * sizeof(void *));
Radek Krejcia8d111f2017-05-31 13:57:37 +02007459 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM, NULL);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007460 *p = reallocated;
7461 data = *p;
7462 data[c + 1] = NULL;
7463 }
7464
7465 return &data[c];
7466}
7467
7468int
7469lyp_yin_parse_complex_ext(struct lys_module *mod, struct lys_ext_instance_complex *ext, struct lyxml_elem *yin,
7470 struct unres_schema *unres)
7471{
Radek Krejciaa9c5202017-02-15 16:10:14 +01007472 struct lyxml_elem *next, *node, *child;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007473 struct lys_type **type;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007474 void **pp, *p, *reallocated;
Radek Krejciaa9c5202017-02-15 16:10:14 +01007475 const char *value, *name;
7476 char *endptr, modifier;
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007477 struct lyext_substmt *info;
7478 long int v;
Radek Krejci5496fae2017-02-10 13:26:48 +01007479 long long int ll;
7480 unsigned long u;
Radek Krejci7417a082017-02-16 11:07:59 +01007481 int i, j;
Radek Krejci8d6b7422017-02-03 14:42:13 +01007482
Radek Krejcia8d111f2017-05-31 13:57:37 +02007483#define YIN_STORE_VALUE(TYPE, FROM, TO) \
7484 *(TYPE **)TO = malloc(sizeof(TYPE)); \
7485 if (!*(TYPE **)TO) { LOGMEM; goto error; } \
7486 (**(TYPE **)TO) = (TYPE)FROM;
7487
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007488#define YIN_EXTCOMPLEX_GETPLACE(STMT, TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007489 p = lys_ext_complex_get_substmt(STMT, ext, &info); \
7490 if (!p) { \
7491 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
7492 goto error; \
7493 } \
7494 if (info->cardinality < LY_STMT_CARD_SOME && (*(TYPE*)p)) { \
7495 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, node->parent->name); \
7496 goto error; \
7497 } \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007498 pp = NULL; i = 0; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007499 if (info->cardinality >= LY_STMT_CARD_SOME) { \
7500 /* there can be multiple instances */ \
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007501 pp = p; \
Radek Krejci5496fae2017-02-10 13:26:48 +01007502 if (!(*pp)) { \
7503 *pp = malloc(2 * sizeof(TYPE)); /* allocate initial array */ \
Radek Krejcia8d111f2017-05-31 13:57:37 +02007504 LY_CHECK_ERR_GOTO(!*pp, LOGMEM, error); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007505 } else { \
7506 for (i = 0; (*(TYPE**)pp)[i]; i++); \
7507 } \
7508 p = &(*(TYPE**)pp)[i]; \
7509 }
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007510#define YIN_EXTCOMPLEX_ENLARGE(TYPE) \
Radek Krejci5496fae2017-02-10 13:26:48 +01007511 if (pp) { \
7512 /* enlarge the array */ \
7513 reallocated = realloc(*pp, (i + 2) * sizeof(TYPE*)); \
Radek Krejcia8d111f2017-05-31 13:57:37 +02007514 LY_CHECK_ERR_GOTO(!reallocated, LOGMEM, error); \
Radek Krejci5496fae2017-02-10 13:26:48 +01007515 *pp = reallocated; \
7516 (*(TYPE**)pp)[i + 1] = 0; \
7517 }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007518#define YIN_EXTCOMPLEX_PARSE_SNODE(STMT, FUNC, ARGS...) \
7519 pp = (void**)yin_getplace_for_extcomplex_node(node, ext, STMT); \
7520 if (!pp) { goto error; } \
Radek Krejci7212e0a2017-03-08 15:58:22 +01007521 if (!FUNC(mod, (struct lys_node*)ext, node, ##ARGS, LYS_PARSE_OPT_CFG_NOINHERIT, unres)) { goto error; }
Radek Krejciaa9c5202017-02-15 16:10:14 +01007522#define YIN_EXTCOMPLEX_PARSE_RESTR(STMT) \
7523 YIN_EXTCOMPLEX_GETPLACE(STMT, struct lys_restr*); \
7524 GETVAL(value, node, "value"); \
7525 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr)); \
Radek Krejcia8d111f2017-05-31 13:57:37 +02007526 LY_CHECK_ERR_GOTO(!*(struct lys_restr **)p, LOGMEM, error); \
Radek Krejciaa9c5202017-02-15 16:10:14 +01007527 (*(struct lys_restr **)p)->expr = lydict_insert(mod->ctx, value, 0); \
7528 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) { \
7529 goto error; \
7530 } \
7531 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007532
Radek Krejci8d6b7422017-02-03 14:42:13 +01007533 LY_TREE_FOR_SAFE(yin->child, next, node) {
7534 if (!node->ns) {
7535 /* garbage */
7536 } else if (node->ns == yin->ns && (ext->flags & LYS_YINELEM) && ly_strequal(node->name, ext->def->argument, 1)) {
7537 /* we have the extension's argument */
7538 if (ext->arg_value) {
7539 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
7540 goto error;
7541 }
7542 ext->arg_value = node->content;
7543 node->content = NULL;
7544 } else if (strcmp(node->ns->value, LY_NSYIN)) {
7545 /* extension */
7546 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_SELF, 0, unres)) {
7547 goto error;
7548 }
7549 } else if (!strcmp(node->name, "description")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007550 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DESCRIPTION, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007551 goto error;
7552 }
7553 } else if (!strcmp(node->name, "reference")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007554 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REFERENCE, 1, "text", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007555 goto error;
7556 }
7557 } else if (!strcmp(node->name, "units")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007558 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_UNITS, 0, "name", unres)) {
Radek Krejci8d6b7422017-02-03 14:42:13 +01007559 goto error;
7560 }
7561 } else if (!strcmp(node->name, "type")) {
7562 type = (struct lys_type **)yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPE);
7563 if (!type) {
7564 goto error;
7565 }
7566 /* allocate type structure */
7567 (*type) = calloc(1, sizeof **type);
Radek Krejcia8d111f2017-05-31 13:57:37 +02007568 LY_CHECK_ERR_GOTO(!*type, LOGMEM, error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007569
7570 /* HACK for unres */
Radek Krejci63fc0962017-02-15 13:20:18 +01007571 lyxml_unlink(mod->ctx, node);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007572 (*type)->der = (struct lys_tpdf *)node;
7573 (*type)->parent = (struct lys_tpdf *)ext;
7574
7575 if (unres_schema_add_node(mod, unres, *type, UNRES_TYPE_DER_EXT, NULL) == -1) {
7576 (*type)->der = NULL;
7577 goto error;
7578 }
7579 continue; /* skip lyxml_free() */
Radek Krejci63fc0962017-02-15 13:20:18 +01007580 } else if (!strcmp(node->name, "typedef")) {
7581 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_TYPEDEF);
7582 if (!pp) {
7583 goto error;
7584 }
7585 /* allocate typedef structure */
7586 (*pp) = calloc(1, sizeof(struct lys_tpdf));
Radek Krejcia8d111f2017-05-31 13:57:37 +02007587 LY_CHECK_ERR_GOTO(!*pp, LOGMEM, error);
Radek Krejci63fc0962017-02-15 13:20:18 +01007588
7589 if (fill_yin_typedef(mod, (struct lys_node *)ext, node, *((struct lys_tpdf **)pp), unres)) {
7590 goto error;
7591 }
Radek Krejci8d6b7422017-02-03 14:42:13 +01007592 } else if (!strcmp(node->name, "if-feature")) {
7593 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_IFFEATURE);
7594 if (!pp) {
7595 goto error;
7596 }
7597 /* allocate iffeature structure */
7598 (*pp) = calloc(1, sizeof(struct lys_iffeature));
Radek Krejcia8d111f2017-05-31 13:57:37 +02007599 LY_CHECK_ERR_GOTO(!*pp, LOGMEM, error);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007600
7601 if (fill_yin_iffeature((struct lys_node *)ext, 0, node, *((struct lys_iffeature **)pp), unres)) {
7602 goto error;
7603 }
7604 } else if (!strcmp(node->name, "status")) {
7605 p = yin_getplace_for_extcomplex_flags(node, ext, LY_STMT_STATUS, LYS_STATUS_MASK);
7606 if (!p) {
7607 goto error;
7608 }
7609
7610 GETVAL(value, node, "value");
7611 if (!strcmp(value, "current")) {
7612 *(uint16_t*)p |= LYS_STATUS_CURR;
7613 } else if (!strcmp(value, "deprecated")) {
7614 *(uint16_t*)p |= LYS_STATUS_DEPRC;
7615 } else if (!strcmp(value, "obsolete")) {
7616 *(uint16_t*)p |= LYS_STATUS_OBSLT;
7617 } else {
7618 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
7619 goto error;
7620 }
7621
7622 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, 0, unres)) {
7623 goto error;
7624 }
Radek Krejcic1885952017-02-07 09:37:51 +01007625 } else if (!strcmp(node->name, "config")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007626 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY, "true", "false", LYS_CONFIG_MASK,
Radek Krejcic1885952017-02-07 09:37:51 +01007627 LYS_CONFIG_W | LYS_CONFIG_SET, LYS_CONFIG_R | LYS_CONFIG_SET, unres)) {
7628 goto error;
7629 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007630 } else if (!strcmp(node->name, "argument")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007631 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ARGUMENT, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007632 goto error;
7633 }
7634 } else if (!strcmp(node->name, "default")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007635 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_DEFAULT, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007636 goto error;
7637 }
Radek Krejcic1885952017-02-07 09:37:51 +01007638 } else if (!strcmp(node->name, "mandatory")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007639 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_MANDATORY,
Radek Krejcic1885952017-02-07 09:37:51 +01007640 "true", "false", LYS_MAND_MASK, LYS_MAND_TRUE, LYS_MAND_FALSE, unres)) {
7641 goto error;
7642 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007643 } else if (!strcmp(node->name, "error-app-tag")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007644 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRTAG, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007645 goto error;
7646 }
7647 } else if (!strcmp(node->name, "error-message")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007648 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ERRMSG, 1, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007649 goto error;
7650 }
7651 } else if (!strcmp(node->name, "prefix")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007652 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PREFIX, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007653 goto error;
7654 }
7655 } else if (!strcmp(node->name, "namespace")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007656 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_NAMESPACE, 0, "uri", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007657 goto error;
7658 }
7659 } else if (!strcmp(node->name, "presence")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007660 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PRESENCE, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007661 goto error;
7662 }
7663 } else if (!strcmp(node->name, "revision-date")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007664 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_REVISIONDATE, 0, "date", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007665 goto error;
7666 }
7667 } else if (!strcmp(node->name, "key")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007668 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_KEY, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007669 goto error;
7670 }
7671 } else if (!strcmp(node->name, "base")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007672 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BASE, 0, "name", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007673 goto error;
7674 }
Radek Krejcic1885952017-02-07 09:37:51 +01007675 } else if (!strcmp(node->name, "ordered-by")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007676 if (yin_parse_extcomplex_flag(mod, node, ext, LY_STMT_ORDEREDBY,
7677 "user", "system", LYS_USERORDERED, LYS_USERORDERED, 0, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007678 goto error;
7679 }
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007680 } else if (!strcmp(node->name, "belongs-to")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007681 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_BELONGSTO, 0, "module", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007682 goto error;
7683 }
7684 } else if (!strcmp(node->name, "contact")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007685 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_CONTACT, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007686 goto error;
7687 }
7688 } else if (!strcmp(node->name, "organization")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007689 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_ORGANIZATION, 1, "text", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007690 goto error;
7691 }
7692 } else if (!strcmp(node->name, "path")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007693 if (yin_parse_extcomplex_str(mod, node, ext, LY_STMT_PATH, 0, "value", unres)) {
Radek Krejci83ac2cd2017-02-06 14:59:47 +01007694 goto error;
7695 }
Radek Krejcic1885952017-02-07 09:37:51 +01007696 } else if (!strcmp(node->name, "require-instance")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007697 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_REQINSTANCE, "true", "false", unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007698 goto error;
7699 }
7700 } else if (!strcmp(node->name, "modifier")) {
Radek Krejcibe336392017-02-07 10:54:24 +01007701 if (yin_parse_extcomplex_bool(mod, node, ext, LY_STMT_MODIFIER, "invert-match", NULL, unres)) {
Radek Krejcic1885952017-02-07 09:37:51 +01007702 goto error;
7703 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007704 } else if (!strcmp(node->name, "fraction-digits")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007705 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_DIGITS, uint8_t);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007706
7707 GETVAL(value, node, "value");
7708 v = strtol(value, NULL, 10);
7709
7710 /* range check */
7711 if (v < 1 || v > 18) {
7712 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
7713 goto error;
7714 }
7715
7716 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_STATUS, i, unres)) {
7717 goto error;
7718 }
7719
7720 /* store the value */
7721 (*(uint8_t *)p) = (uint8_t)v;
7722
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007723 YIN_EXTCOMPLEX_ENLARGE(uint8_t);
Radek Krejci5496fae2017-02-10 13:26:48 +01007724 } else if (!strcmp(node->name, "max-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007725 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MAX, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007726
7727 GETVAL(value, node, "value");
7728 while (isspace(value[0])) {
7729 value++;
7730 }
7731
7732 if (!strcmp(value, "unbounded")) {
7733 u = 0;
7734 } else {
7735 /* convert it to uint32_t */
7736 errno = 0; endptr = NULL;
7737 u = strtoul(value, &endptr, 10);
7738 if (*endptr || value[0] == '-' || errno || u == 0 || u > UINT32_MAX) {
7739 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007740 goto error;
7741 }
Radek Krejci3a14dfd2017-02-07 13:27:33 +01007742 }
Radek Krejci5496fae2017-02-10 13:26:48 +01007743
7744 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
7745 goto error;
7746 }
7747
7748 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02007749 YIN_STORE_VALUE(uint32_t, u, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01007750
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007751 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007752 } else if (!strcmp(node->name, "min-elements")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007753 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_MIN, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007754
7755 GETVAL(value, node, "value");
7756 while (isspace(value[0])) {
7757 value++;
7758 }
7759
7760 /* convert it to uint32_t */
7761 errno = 0;
7762 endptr = NULL;
7763 u = strtoul(value, &endptr, 10);
7764 if (*endptr || value[0] == '-' || errno || u > UINT32_MAX) {
7765 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
7766 goto error;
7767 }
7768
7769 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_MAX, i, unres)) {
7770 goto error;
7771 }
7772
7773 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02007774 YIN_STORE_VALUE(uint32_t, u, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01007775
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007776 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci06a9aa02017-02-17 10:50:24 +01007777 } else if (!strcmp(node->name, "value")) {
PavolVican2ed9f4e2017-02-16 00:08:45 +01007778 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_VALUE, int32_t*);
7779
7780 GETVAL(value, node, "value");
7781 while (isspace(value[0])) {
7782 value++;
7783 }
7784
7785 /* convert it to int32_t */
Radek Krejci9326fc02017-02-16 09:57:40 +01007786 ll = strtoll(value, NULL, 10);
PavolVican2ed9f4e2017-02-16 00:08:45 +01007787
7788 /* range check */
Radek Krejci9326fc02017-02-16 09:57:40 +01007789 if (ll < INT32_MIN || ll > INT32_MAX) {
PavolVican2ed9f4e2017-02-16 00:08:45 +01007790 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
7791 goto error;
7792 }
7793
7794 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_VALUE, i, unres)) {
7795 goto error;
7796 }
7797
7798 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02007799 YIN_STORE_VALUE(int32_t, ll, p)
PavolVican2ed9f4e2017-02-16 00:08:45 +01007800
7801 YIN_EXTCOMPLEX_ENLARGE(int32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007802 } else if (!strcmp(node->name, "position")) {
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007803 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_POSITION, uint32_t*);
Radek Krejci5496fae2017-02-10 13:26:48 +01007804
7805 GETVAL(value, node, "value");
7806 ll = strtoll(value, NULL, 10);
7807
7808 /* range check */
7809 if (ll < 0 || ll > UINT32_MAX) {
7810 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
7811 goto error;
7812 }
7813
7814 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_POSITION, i, unres)) {
7815 goto error;
7816 }
7817
7818 /* store the value */
Radek Krejcia8d111f2017-05-31 13:57:37 +02007819 YIN_STORE_VALUE(uint32_t, ll, p)
Radek Krejci5496fae2017-02-10 13:26:48 +01007820
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007821 YIN_EXTCOMPLEX_ENLARGE(uint32_t*);
Radek Krejci37f9ba32017-02-10 16:50:35 +01007822 } else if (!strcmp(node->name, "module")) {
7823 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MODULE);
7824 if (!pp) {
7825 goto error;
7826 }
7827
7828 *(struct lys_module **)pp = yin_read_module_(mod->ctx, node, NULL, mod->implemented);
7829 if (!(*pp)) {
7830 goto error;
7831 }
Radek Krejcic5cc5302017-02-16 10:07:46 +01007832 } else if (!strcmp(node->name, "when")) {
7833 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_WHEN, struct lys_when*);
7834
7835 *(struct lys_when**)p = read_yin_when(mod, node, unres);
7836 if (!*(struct lys_when**)p) {
7837 goto error;
7838 }
7839
7840 YIN_EXTCOMPLEX_ENLARGE(struct lys_when*);
Radek Krejci7417a082017-02-16 11:07:59 +01007841 } else if (!strcmp(node->name, "revision")) {
7842 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_REVISION, struct lys_revision*);
7843
7844 *(struct lys_revision**)p = calloc(1, sizeof(struct lys_revision));
Radek Krejcia8d111f2017-05-31 13:57:37 +02007845 LY_CHECK_ERR_GOTO(!*(struct lys_revision**)p, LOGMEM, error);
Radek Krejci7417a082017-02-16 11:07:59 +01007846 if (fill_yin_revision(mod, node, *(struct lys_revision**)p, unres)) {
7847 goto error;
7848 }
7849
7850 /* check uniqueness of the revision dates - not required by RFC */
7851 if (pp) {
7852 for (j = 0; j < i; j++) {
7853 if (!strcmp((*(struct lys_revision***)pp)[j]->date, (*(struct lys_revision**)p)->date)) {
7854 LOGWRN("Module's revisions are not unique (%s).", (*(struct lys_revision**)p)->date);
7855 }
7856 }
7857 }
7858
7859 YIN_EXTCOMPLEX_ENLARGE(struct lys_revision*);
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007860 } else if (!strcmp(node->name, "unique")) {
7861 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_UNIQUE, struct lys_unique*);
7862
7863 *(struct lys_unique**)p = calloc(1, sizeof(struct lys_unique));
Radek Krejcia8d111f2017-05-31 13:57:37 +02007864 LY_CHECK_ERR_GOTO(!*(struct lys_unique**)p, LOGMEM, error);
Radek Krejcic3f1b6f2017-02-15 10:51:10 +01007865 if (fill_yin_unique(mod, (struct lys_node*)ext, node, *(struct lys_unique**)p, unres)) {
7866 goto error;
7867 }
7868
7869 if (lyp_yin_parse_subnode_ext(mod, ext, LYEXT_PAR_EXTINST, node, LYEXT_SUBSTMT_UNIQUE, i, unres)) {
7870 goto error;
7871 }
7872 YIN_EXTCOMPLEX_ENLARGE(struct lys_unique*);
Radek Krejcif95b6292017-02-13 15:57:37 +01007873 } else if (!strcmp(node->name, "action")) {
7874 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ACTION, read_yin_rpc_action);
7875 } else if (!strcmp(node->name, "anydata")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007876 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYDATA, read_yin_anydata, LYS_ANYDATA);
Radek Krejcif95b6292017-02-13 15:57:37 +01007877 } else if (!strcmp(node->name, "anyxml")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007878 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_ANYXML, read_yin_anydata, LYS_ANYXML);
Radek Krejcif95b6292017-02-13 15:57:37 +01007879 } else if (!strcmp(node->name, "case")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007880 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CASE, read_yin_case);
Radek Krejcif95b6292017-02-13 15:57:37 +01007881 } else if (!strcmp(node->name, "choice")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007882 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CHOICE, read_yin_choice);
Radek Krejcif95b6292017-02-13 15:57:37 +01007883 } else if (!strcmp(node->name, "container")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007884 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_CONTAINER, read_yin_container);
Radek Krejcif95b6292017-02-13 15:57:37 +01007885 } else if (!strcmp(node->name, "grouping")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007886 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_GROUPING, read_yin_grouping);
Radek Krejcif95b6292017-02-13 15:57:37 +01007887 } else if (!strcmp(node->name, "output")) {
7888 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_OUTPUT, read_yin_input_output);
7889 } else if (!strcmp(node->name, "input")) {
7890 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_INPUT, read_yin_input_output);
7891 } else if (!strcmp(node->name, "leaf")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007892 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAF, read_yin_leaf);
Radek Krejcif95b6292017-02-13 15:57:37 +01007893 } else if (!strcmp(node->name, "leaf-list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007894 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LEAFLIST, read_yin_leaflist);
Radek Krejcif95b6292017-02-13 15:57:37 +01007895 } else if (!strcmp(node->name, "list")) {
Radek Krejci7212e0a2017-03-08 15:58:22 +01007896 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_LIST, read_yin_list);
Radek Krejcif95b6292017-02-13 15:57:37 +01007897 } else if (!strcmp(node->name, "notification")) {
7898 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_NOTIFICATION, read_yin_notif);
7899 } else if (!strcmp(node->name, "uses")) {
7900 YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_USES, read_yin_uses);
Radek Krejciaa9c5202017-02-15 16:10:14 +01007901 } else if (!strcmp(node->name, "length")) {
7902 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_LENGTH);
7903 } else if (!strcmp(node->name, "must")) {
7904 pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MUST);
7905 if (!pp) {
7906 goto error;
7907 }
7908 /* allocate structure for must */
7909 (*pp) = calloc(1, sizeof(struct lys_restr));
Radek Krejcia8d111f2017-05-31 13:57:37 +02007910 LY_CHECK_ERR_GOTO(!*pp, LOGMEM, error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01007911
7912 if (fill_yin_must(mod, node, *((struct lys_restr **)pp), unres)) {
7913 goto error;
7914 }
7915 } else if (!strcmp(node->name, "pattern")) {
7916 YIN_EXTCOMPLEX_GETPLACE(LY_STMT_PATTERN, struct lys_restr*);
7917 GETVAL(value, node, "value");
7918 if (lyp_check_pattern(value, NULL)) {
7919 goto error;
7920 }
7921
7922 *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr));
Radek Krejcia8d111f2017-05-31 13:57:37 +02007923 LY_CHECK_ERR_GOTO(!*(struct lys_restr **)p, LOGMEM, error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01007924 (*(struct lys_restr **)p)->expr = lydict_insert(mod->ctx, value, 0);
7925
7926 modifier = 0x06; /* ACK */
7927 if (mod->version >= 2) {
7928 name = NULL;
7929 LY_TREE_FOR(node->child, child) {
7930 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
7931 if (name) {
7932 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
7933 goto error;
7934 }
7935
7936 GETVAL(name, child, "value");
7937 if (!strcmp(name, "invert-match")) {
7938 modifier = 0x15; /* NACK */
7939 } else {
7940 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
7941 goto error;
7942 }
7943 /* get extensions of the modifier */
7944 if (lyp_yin_parse_subnode_ext(mod, *(struct lys_restr **)p, LYEXT_PAR_RESTR, child,
7945 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
7946 goto error;
7947 }
7948 }
7949 }
7950 }
7951
7952 /* store the value: modifier byte + value + terminating NULL byte */
7953 (*(struct lys_restr **)p)->expr = malloc((strlen(value) + 2) * sizeof(char));
Radek Krejcia8d111f2017-05-31 13:57:37 +02007954 LY_CHECK_ERR_GOTO(!(*(struct lys_restr **)p)->expr, LOGMEM, error);
Radek Krejciaa9c5202017-02-15 16:10:14 +01007955 ((char *)(*(struct lys_restr **)p)->expr)[0] = modifier;
7956 strcpy(&((char *)(*(struct lys_restr **)p)->expr)[1], value);
7957 lydict_insert_zc(mod->ctx, (char *)(*(struct lys_restr **)p)->expr);
7958
7959 /* get possible sub-statements */
7960 if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) {
7961 goto error;
7962 }
7963
7964 YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
7965 } else if (!strcmp(node->name, "range")) {
7966 YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_RANGE);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007967 } else {
Radek Krejci06a9aa02017-02-17 10:50:24 +01007968 LOGERR(LY_SUCCESS, "Extension's substatement \"%s\" not supported.", node->name);
7969 //LOGERR(LY_EINT, "Extension's substatement \"%s\" not supported.", node->name);
Radek Krejci8d6b7422017-02-03 14:42:13 +01007970 //return EXIT_FAILURE;
7971 }
7972 lyxml_free(mod->ctx, node);
7973 }
7974
PavolVicanc4b798e2017-02-20 23:15:27 +01007975 if (ext->substmt && lyp_mand_check_ext(ext, yin->name)) {
7976 return EXIT_FAILURE;
Radek Krejci06a9aa02017-02-17 10:50:24 +01007977 }
7978
Radek Krejci8d6b7422017-02-03 14:42:13 +01007979 return EXIT_SUCCESS;
7980
7981error:
7982 return EXIT_FAILURE;
7983}