blob: d1cf6dd8221b60a29bca213ceab9b386d79180f6 [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
2 * @file yin.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief YIN parser for libyang
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Radek Krejci54f6fb32016-02-24 12:56:39 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
Michal Vasko8de098c2016-02-26 10:00:25 +010011 *
Radek Krejci54f6fb32016-02-24 12:56:39 +010012 * https://opensource.org/licenses/BSD-3-Clause
Radek Krejcida04f4a2015-05-21 12:54:09 +020013 */
14
Radek Krejci812b10a2015-05-28 16:48:25 +020015#include <assert.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020016#include <ctype.h>
Radek Krejci8b4f23c2015-06-02 16:09:25 +020017#include <errno.h>
18#include <limits.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020019#include <stdint.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020020#include <stdlib.h>
21#include <string.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020022#include <stddef.h>
Michal Vasko69068852015-07-13 14:34:31 +020023#include <sys/types.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020024
Radek Krejci998a0b82015-08-17 13:14:36 +020025#include "libyang.h"
26#include "common.h"
27#include "context.h"
Radek Krejci41912fe2015-10-22 10:22:12 +020028#include "dict_private.h"
Michal Vaskofcdac172015-10-07 09:35:05 +020029#include "xpath.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020030#include "parser.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020031#include "resolve.h"
32#include "tree_internal.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020033#include "xml_internal.h"
Radek Krejciefdd0ce2015-05-26 16:48:29 +020034
Radek Krejciadb57612016-02-16 13:34:34 +010035#define GETVAL(value, node, arg) \
36 value = lyxml_get_attr(node, arg, NULL); \
37 if (!value) { \
Radek Krejci48464ed2016-03-17 15:44:09 +010038 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, arg, node->name); \
Radek Krejciadb57612016-02-16 13:34:34 +010039 goto error; \
Michal Vasko2d710f32016-02-05 12:29:21 +010040 }
Radek Krejcice7fb782015-05-29 16:52:34 +020041
Michal Vaskoe022a562016-09-27 14:24:15 +020042#define OPT_IDENT 0x01
43#define OPT_CFG_PARSE 0x02
44#define OPT_CFG_INHERIT 0x04
45#define OPT_CFG_IGNORE 0x08
46#define OPT_MODULE 0x10
Radek Krejci07d0fb92017-01-13 14:11:05 +010047static int read_yin_common(struct lys_module *, struct lys_node *, void *, LYEXT_PAR, struct lyxml_elem *, int,
48 struct unres_schema *);
Radek Krejcib388c152015-06-04 17:03:03 +020049
Radek Krejcib8048692015-08-05 13:36:34 +020050static struct lys_node *read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020051 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020052static struct lys_node *read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020053 int valid_config, struct unres_schema *unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +020054static struct lys_node *read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020055 LYS_NODE type, int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020056static struct lys_node *read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020057 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020058static struct lys_node *read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020059 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020060static struct lys_node *read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020061 int valid_config, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020062static struct lys_node *read_yin_list(struct lys_module *module,struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020063 int valid_config, struct unres_schema *unres);
Radek Krejcia9544502015-08-14 08:24:29 +020064static struct lys_node *read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci3440cc52016-06-23 17:03:59 +020065 struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020066static struct lys_node *read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020067 int valid_config, struct unres_schema *unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +020068static struct lys_node *read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020069 struct unres_schema *unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +020070static struct lys_node *read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoe022a562016-09-27 14:24:15 +020071 struct unres_schema *unres);
Radek Krejci5323b492017-01-16 15:40:11 +010072static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres);
Radek Krejci74705112015-06-05 10:25:44 +020073
Radek Krejci07d0fb92017-01-13 14:11:05 +010074/*
75 * yin - the provided XML subtree is unlinked
Radek Krejci2b999ac2017-01-18 16:22:12 +010076 * ext - pointer to the storage in the parent structure to be able to update its location after realloc
Radek Krejci07d0fb92017-01-13 14:11:05 +010077 */
78int
79lyp_yin_fill_ext(void *parent, LYEXT_PAR parent_type, LYEXT_SUBSTMT substmt, uint8_t substmt_index,
Radek Krejci2b999ac2017-01-18 16:22:12 +010080 struct lys_module *module, struct lyxml_elem *yin, struct lys_ext_instance ***ext,
81 uint8_t ext_index, struct unres_schema *unres)
Radek Krejci07d0fb92017-01-13 14:11:05 +010082{
83 struct unres_ext *info;
84
85 info = malloc(sizeof *info);
86 lyxml_unlink(module->ctx, yin);
87 info->data.yin = yin;
88 info->datatype = LYS_IN_YIN;
89 info->parent = parent;
Radek Krejcia7db9702017-01-20 12:55:14 +010090 info->mod = module;
Radek Krejci07d0fb92017-01-13 14:11:05 +010091 info->parent_type = parent_type;
92 info->substmt = substmt;
93 info->substmt_index = substmt_index;
Radek Krejci2b999ac2017-01-18 16:22:12 +010094 info->ext_index = ext_index;
Radek Krejci07d0fb92017-01-13 14:11:05 +010095
96 if (unres_schema_add_node(module, unres, ext, UNRES_EXT, (struct lys_node *)info) == -1) {
97 return EXIT_FAILURE;
98 }
99
100 return EXIT_SUCCESS;
101}
102
Michal Vasko0d343d12015-08-24 14:57:36 +0200103/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200104static const char *
105read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +0200106{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200107 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200108
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200109 /* there should be <text> child */
110 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
Radek Krejci218436d2016-02-10 12:54:06 +0100111 LOGERR(LY_EVALID, "Expected \"%s\" element in \"%s\" element.", name, node->name);
Radek Krejci48464ed2016-03-17 15:44:09 +0100112 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, node->name);
Radek Krejci218436d2016-02-10 12:54:06 +0100113 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200114 } else if (node->child->content) {
115 len = strlen(node->child->content);
116 return lydict_insert(ctx, node->child->content, len);
Radek Krejci218436d2016-02-10 12:54:06 +0100117 } else {
118 return lydict_insert(ctx, "", 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200119 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200120}
121
Radek Krejcie534c132016-11-23 13:32:31 +0100122static int
Radek Krejci07d0fb92017-01-13 14:11:05 +0100123read_yin_subnode_ext(struct lys_module *mod, void *elem, LYEXT_PAR elem_type,
Radek Krejciac00b2a2017-01-17 14:05:00 +0100124 struct lyxml_elem *yin, LYEXT_SUBSTMT type, uint8_t i, struct unres_schema *unres)
Radek Krejcie534c132016-11-23 13:32:31 +0100125{
Radek Krejci07d0fb92017-01-13 14:11:05 +0100126 void *reallocated;
127 struct lyxml_elem *next, *child;
128 int r;
129 struct lys_ext_instance ***ext;
130 uint8_t *ext_size;
Radek Krejcie534c132016-11-23 13:32:31 +0100131
Radek Krejci07d0fb92017-01-13 14:11:05 +0100132 switch (elem_type) {
133 case LYEXT_PAR_MODULE:
134 ext_size = &((struct lys_module *)elem)->ext_size;
135 ext = &((struct lys_module *)elem)->ext;
136 break;
Radek Krejci95f22ae2017-01-20 14:25:53 +0100137 case LYEXT_PAR_IMPORT:
138 ext_size = &((struct lys_import *)elem)->ext_size;
139 ext = &((struct lys_import *)elem)->ext;
140 break;
141 case LYEXT_PAR_INCLUDE:
142 ext_size = &((struct lys_include *)elem)->ext_size;
143 ext = &((struct lys_include *)elem)->ext;
144 break;
145 case LYEXT_PAR_REVISION:
146 ext_size = &((struct lys_revision *)elem)->ext_size;
147 ext = &((struct lys_revision *)elem)->ext;
148 break;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100149 case LYEXT_PAR_NODE:
150 ext_size = &((struct lys_node *)elem)->ext_size;
151 ext = &((struct lys_node *)elem)->ext;
152 break;
153 case LYEXT_PAR_IDENT:
154 ext_size = &((struct lys_ident *)elem)->ext_size;
155 ext = &((struct lys_ident *)elem)->ext;
156 break;
Radek Krejci47f7ea52017-01-23 13:14:09 +0100157 case LYEXT_PAR_TYPE:
158 ext_size = &((struct lys_type *)elem)->ext_size;
159 ext = &((struct lys_type *)elem)->ext;
160 break;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100161 case LYEXT_PAR_TYPE_BIT:
162 ext_size = &((struct lys_type_bit *)elem)->ext_size;
163 ext = &((struct lys_type_bit *)elem)->ext;
164 break;
165 case LYEXT_PAR_TYPE_ENUM:
166 ext_size = &((struct lys_type_enum *)elem)->ext_size;
167 ext = &((struct lys_type_enum *)elem)->ext;
168 break;
169 case LYEXT_PAR_TPDF:
170 ext_size = &((struct lys_tpdf *)elem)->ext_size;
171 ext = &((struct lys_tpdf *)elem)->ext;
172 break;
173 case LYEXT_PAR_EXT:
174 ext_size = &((struct lys_ext *)elem)->ext_size;
175 ext = &((struct lys_ext *)elem)->ext;
176 break;
177 case LYEXT_PAR_FEATURE:
178 ext_size = &((struct lys_feature *)elem)->ext_size;
179 ext = &((struct lys_feature *)elem)->ext;
180 break;
181 case LYEXT_PAR_REFINE:
182 ext_size = &((struct lys_refine *)elem)->ext_size;
183 ext = &((struct lys_refine *)elem)->ext;
184 break;
Radek Krejcifdc0d702017-01-23 15:58:38 +0100185 case LYEXT_PAR_RESTR:
Radek Krejcifccd1442017-01-16 10:26:57 +0100186 ext_size = &((struct lys_restr *)elem)->ext_size;
187 ext = &((struct lys_restr *)elem)->ext;
188 break;
Radek Krejci5323b492017-01-16 15:40:11 +0100189 case LYEXT_PAR_WHEN:
190 ext_size = &((struct lys_when *)elem)->ext_size;
191 ext = &((struct lys_when *)elem)->ext;
192 break;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +0100193 case LYEXT_PAR_DEVIATE:
194 ext_size = &((struct lys_deviate *)elem)->ext_size;
195 ext = &((struct lys_deviate *)elem)->ext;
196 break;
197 case LYEXT_PAR_DEVIATION:
198 ext_size = &((struct lys_deviation *)elem)->ext_size;
199 ext = &((struct lys_deviation *)elem)->ext;
200 break;
Radek Krejci07d0fb92017-01-13 14:11:05 +0100201 default:
Radek Krejcifccd1442017-01-16 10:26:57 +0100202 LOGERR(LY_EINT, "parent type %d", elem_type);
Radek Krejcie534c132016-11-23 13:32:31 +0100203 return EXIT_FAILURE;
204 }
205
Radek Krejcifccd1442017-01-16 10:26:57 +0100206 if (type == LYEXT_SUBSTMT_SELF) {
207 /* parse for the statement self, not for the substatement */
208 child = yin;
209 next = NULL;
210 goto parseext;
211 }
212
Radek Krejci07d0fb92017-01-13 14:11:05 +0100213 LY_TREE_FOR_SAFE(yin->child, next, child) {
214 if (!strcmp(child->ns->value, LY_NSYIN)) {
215 /* skip the regular YIN nodes */
216 continue;
217 }
218
219 /* parse it as extension */
Radek Krejcifccd1442017-01-16 10:26:57 +0100220parseext:
Radek Krejci07d0fb92017-01-13 14:11:05 +0100221
222 /* first, allocate a space for the extension instance in the parent elem */
223 reallocated = realloc(*ext, (1 + (*ext_size)) * sizeof **ext);
224 if (!reallocated) {
225 LOGMEM;
226 return EXIT_FAILURE;
227 }
228 (*ext) = reallocated;
229
230 /* init memory */
231 (*ext)[(*ext_size)] = NULL;
232
233 /* parse YIN data */
Radek Krejci2b999ac2017-01-18 16:22:12 +0100234 r = lyp_yin_fill_ext(elem, elem_type, type, i, mod, child, &(*ext), (*ext_size), unres);
Radek Krejci07d0fb92017-01-13 14:11:05 +0100235 (*ext_size)++;
236 if (r) {
237 return EXIT_FAILURE;
238 }
239
Radek Krejcifccd1442017-01-16 10:26:57 +0100240 /* done - do not free the child, it is unlinked in lyp_yin_fill_ext */
Radek Krejci07d0fb92017-01-13 14:11:05 +0100241 }
242
Radek Krejcie534c132016-11-23 13:32:31 +0100243 return EXIT_SUCCESS;
244}
245
Michal Vasko0d343d12015-08-24 14:57:36 +0200246/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200247static int
Radek Krejci9de2c042016-10-19 16:53:06 +0200248fill_yin_iffeature(struct lys_node *parent, int parent_is_feature, struct lyxml_elem *yin, struct lys_iffeature *iffeat,
249 struct unres_schema *unres)
Michal Vasko1d337e12016-02-15 12:32:04 +0100250{
Radek Krejci5323b492017-01-16 15:40:11 +0100251 int r, c_ext = 0;
Michal Vasko1d337e12016-02-15 12:32:04 +0100252 const char *value;
Radek Krejci5323b492017-01-16 15:40:11 +0100253 struct lyxml_elem *node, *next;
Michal Vasko1d337e12016-02-15 12:32:04 +0100254
255 GETVAL(value, yin, "name");
Michal Vasko97b32be2016-07-25 10:59:53 +0200256
257 if ((lys_node_module(parent)->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
258 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
Radek Krejci9ff0a922016-07-14 13:08:05 +0200259error:
Michal Vasko1d337e12016-02-15 12:32:04 +0100260 return EXIT_FAILURE;
261 }
262
Michal Vasko56d082c2016-10-25 14:00:42 +0200263 if (!(value = transform_iffeat_schema2json(parent->module, value))) {
Michal Vasko1d337e12016-02-15 12:32:04 +0100264 return EXIT_FAILURE;
265 }
266
Radek Krejci9de2c042016-10-19 16:53:06 +0200267 r = resolve_iffeature_compile(iffeat, value, parent, parent_is_feature, unres);
Michal Vasko1d337e12016-02-15 12:32:04 +0100268 lydict_remove(parent->module->ctx, value);
Radek Krejci9ff0a922016-07-14 13:08:05 +0200269 if (r) {
270 return EXIT_FAILURE;
Michal Vasko1d337e12016-02-15 12:32:04 +0100271 }
272
Radek Krejci5323b492017-01-16 15:40:11 +0100273 LY_TREE_FOR_SAFE(yin->child, next, node) {
274 if (!node->ns) {
275 /* garbage */
276 lyxml_free(parent->module->ctx, node);
277 } else if (strcmp(node->ns->value, LY_NSYIN)) {
278 /* extension */
279 c_ext++;
280 } else {
281 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "if-feature");
282 return EXIT_FAILURE;
283 }
284 }
285 if (c_ext) {
286 iffeat->ext = calloc(c_ext, sizeof *iffeat->ext);
287 if (!iffeat->ext) {
288 LOGMEM;
289 return EXIT_FAILURE;
290 }
291 LY_TREE_FOR_SAFE(yin->child, next, node) {
292 /* extensions */
293 r = lyp_yin_fill_ext(iffeat, LYEXT_PAR_IDENT, 0, 0, parent->module, node,
Radek Krejci2b999ac2017-01-18 16:22:12 +0100294 &iffeat->ext, iffeat->ext_size, unres);
Radek Krejci5323b492017-01-16 15:40:11 +0100295 iffeat->ext_size++;
296 if (r) {
297 return EXIT_FAILURE;
298 }
299 }
300 }
301
Radek Krejci9ff0a922016-07-14 13:08:05 +0200302 return EXIT_SUCCESS;
Michal Vasko1d337e12016-02-15 12:32:04 +0100303}
304
305/* logs directly */
306static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200307fill_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 +0200308{
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200309 struct lyxml_elem *node, *next;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200310 const char *value;
Radek Krejci018f1f52016-08-03 16:01:20 +0200311 int rc;
Radek Krejcie534c132016-11-23 13:32:31 +0100312 int c_ftrs = 0, c_base = 0, c_ext = 0;
Radek Krejci18a44882017-01-23 13:47:29 +0100313 void *reallocated;
Radek Krejci04581c62015-05-22 21:24:00 +0200314
Michal Vasko4cfcd252015-08-03 14:31:10 +0200315 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100316 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200317
Radek Krejci07d0fb92017-01-13 14:11:05 +0100318 if (read_yin_common(module, NULL, ident, LYEXT_PAR_IDENT, yin, OPT_IDENT | OPT_MODULE, unres)) {
Radek Krejci18a44882017-01-23 13:47:29 +0100319 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200320 }
Radek Krejci04581c62015-05-22 21:24:00 +0200321
Pavol Vicand6cda452016-07-13 15:08:29 +0200322 if (dup_identities_check(ident->name, module)) {
Radek Krejci18a44882017-01-23 13:47:29 +0100323 goto error;
Pavol Vicand6cda452016-07-13 15:08:29 +0200324 }
325
Radek Krejcie534c132016-11-23 13:32:31 +0100326 LY_TREE_FOR(yin->child, node) {
327 if (strcmp(node->ns->value, LY_NSYIN)) {
328 /* extension */
329 c_ext++;
330 } else if (!strcmp(node->name, "base")) {
Radek Krejci018f1f52016-08-03 16:01:20 +0200331 if (c_base && (module->version < 2)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100332 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci18a44882017-01-23 13:47:29 +0100333 goto error;
334 }
335 if (read_yin_subnode_ext(module, ident, LYEXT_PAR_IDENT, node, LYEXT_SUBSTMT_BASE, c_base, unres)) {
336 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200337 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200338 c_base++;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100339
Radek Krejci018f1f52016-08-03 16:01:20 +0200340 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
341 c_ftrs++;
342
343 } else {
344 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
Radek Krejci18a44882017-01-23 13:47:29 +0100345 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200346 }
347 }
348
349 if (c_base) {
350 ident->base_size = 0;
351 ident->base = calloc(c_base, sizeof *ident->base);
352 if (!ident->base) {
353 LOGMEM;
Radek Krejci18a44882017-01-23 13:47:29 +0100354 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200355 }
356 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200357 if (c_ftrs) {
358 ident->iffeature = calloc(c_ftrs, sizeof *ident->iffeature);
359 if (!ident->iffeature) {
360 LOGMEM;
Radek Krejci18a44882017-01-23 13:47:29 +0100361 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200362 }
363 }
Radek Krejcie534c132016-11-23 13:32:31 +0100364 if (c_ext) {
Radek Krejci18a44882017-01-23 13:47:29 +0100365 /* some extensions may be already present from the substatements */
366 reallocated = realloc(ident->ext, (c_ext + ident->ext_size) * sizeof *ident->ext);
367 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +0100368 LOGMEM;
Radek Krejci18a44882017-01-23 13:47:29 +0100369 goto error;
Radek Krejcie534c132016-11-23 13:32:31 +0100370 }
Radek Krejci18a44882017-01-23 13:47:29 +0100371 ident->ext = reallocated;
372
373 /* init memory */
374 memset(&ident->ext[ident->ext_size], 0, c_ext * sizeof *ident->ext);
Radek Krejcie534c132016-11-23 13:32:31 +0100375 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200376
Radek Krejcie534c132016-11-23 13:32:31 +0100377 LY_TREE_FOR_SAFE(yin->child, next, node) {
378 if (strcmp(node->ns->value, LY_NSYIN)) {
379 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +0100380 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 +0100381 ident->ext_size++;
382 if (rc) {
383 goto error;
384 }
385 } else if (!strcmp(node->name, "base")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200386 GETVAL(value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100387 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100388 if (!value) {
Radek Krejci18a44882017-01-23 13:47:29 +0100389 goto error;
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200390 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100391
Radek Krejci48464ed2016-03-17 15:44:09 +0100392 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vaskoc94283a2015-10-29 09:07:20 +0100393 lydict_remove(module->ctx, value);
Radek Krejci18a44882017-01-23 13:47:29 +0100394 goto error;
Michal Vaskoc94283a2015-10-29 09:07:20 +0100395 }
396 lydict_remove(module->ctx, value);
Radek Krejci018f1f52016-08-03 16:01:20 +0200397 } else if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200398 rc = fill_yin_iffeature((struct lys_node *)ident, 0, node, &ident->iffeature[ident->iffeature_size], unres);
Radek Krejci018f1f52016-08-03 16:01:20 +0200399 ident->iffeature_size++;
400 if (rc) {
Radek Krejci18a44882017-01-23 13:47:29 +0100401 goto error;
Radek Krejci018f1f52016-08-03 16:01:20 +0200402 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200403 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200404 }
Radek Krejci04581c62015-05-22 21:24:00 +0200405
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200406 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200407
408error:
409 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200410}
411
Michal Vasko0d343d12015-08-24 14:57:36 +0200412/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200413static int
Radek Krejcifccd1442017-01-16 10:26:57 +0100414read_restr_substmt(struct lys_module *module, LYEXT_PAR restr_type, struct lys_restr *restr, struct lyxml_elem *yin,
415 struct unres_schema *unres)
Radek Krejci41726f92015-06-19 13:11:05 +0200416{
Radek Krejcifccd1442017-01-16 10:26:57 +0100417 struct lyxml_elem *child, *next;
Radek Krejci461d1622015-06-30 14:06:28 +0200418 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200419
Radek Krejcifccd1442017-01-16 10:26:57 +0100420 LY_TREE_FOR_SAFE(yin->child, next, child) {
421 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200422 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200423 continue;
Radek Krejcifccd1442017-01-16 10:26:57 +0100424 } else if (strcmp(child->ns->value, LY_NSYIN)) {
425 /* extension */
Radek Krejciac00b2a2017-01-17 14:05:00 +0100426 if (read_yin_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100427 return EXIT_FAILURE;
428 }
429 } else if (!strcmp(child->name, "description")) {
Radek Krejci41726f92015-06-19 13:11:05 +0200430 if (restr->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100431 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200432 return EXIT_FAILURE;
433 }
Radek Krejciac00b2a2017-01-17 14:05:00 +0100434 if (read_yin_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100435 return EXIT_FAILURE;
436 }
437 restr->dsc = read_yin_subnode(module->ctx, child, "text");
Radek Krejci41726f92015-06-19 13:11:05 +0200438 if (!restr->dsc) {
439 return EXIT_FAILURE;
440 }
441 } else if (!strcmp(child->name, "reference")) {
442 if (restr->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100443 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200444 return EXIT_FAILURE;
445 }
Radek Krejciac00b2a2017-01-17 14:05:00 +0100446 if (read_yin_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100447 return EXIT_FAILURE;
448 }
449 restr->ref = read_yin_subnode(module->ctx, child, "text");
Radek Krejci41726f92015-06-19 13:11:05 +0200450 if (!restr->ref) {
451 return EXIT_FAILURE;
452 }
453 } else if (!strcmp(child->name, "error-app-tag")) {
454 if (restr->eapptag) {
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 Krejciac00b2a2017-01-17 14:05:00 +0100458 if (read_yin_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_ERRTAG, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100459 return EXIT_FAILURE;
460 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200461 GETVAL(value, child, "value");
Radek Krejcifccd1442017-01-16 10:26:57 +0100462 restr->eapptag = lydict_insert(module->ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200463 } else if (!strcmp(child->name, "error-message")) {
464 if (restr->emsg) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100465 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200466 return EXIT_FAILURE;
467 }
Radek Krejciac00b2a2017-01-17 14:05:00 +0100468 if (read_yin_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_ERRMSG, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +0100469 return EXIT_FAILURE;
470 }
471 restr->emsg = read_yin_subnode(module->ctx, child, "value");
Radek Krejci41726f92015-06-19 13:11:05 +0200472 if (!restr->emsg) {
473 return EXIT_FAILURE;
474 }
475 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100476 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200477 return EXIT_FAILURE;
478 }
Radek Krejci41726f92015-06-19 13:11:05 +0200479 }
480
481 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200482
483error:
484 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200485}
486
Michal Vasko88c29542015-11-27 14:57:53 +0100487/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
488int
Radek Krejcib8048692015-08-05 13:36:34 +0200489fill_yin_type(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_type *type,
Radek Krejci3a5501d2016-07-18 22:03:34 +0200490 int tpdftype, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200491{
Michal Vasko0aee5c12016-06-17 14:27:26 +0200492 const char *value, *name;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200493 struct lys_node *siter;
Radek Krejcie534c132016-11-23 13:32:31 +0100494 struct lyxml_elem *next, *next2, *node, *child, exts;
Radek Krejcifccd1442017-01-16 10:26:57 +0100495 struct lys_restr **restrs, *restr;
Radek Krejci1c5890d2016-08-02 13:15:42 +0200496 struct lys_type_bit bit, *bits_sc = NULL;
497 struct lys_type_enum *enms_sc = NULL; /* shortcut */
Radek Krejcie663e012016-08-01 17:12:34 +0200498 struct lys_type *dertype;
Radek Krejcie534c132016-11-23 13:32:31 +0100499 int i, j, rc, val_set, c_ftrs, c_ext = 0;
Radek Krejcidc008d72016-02-17 13:12:14 +0100500 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200501 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200502 int64_t p, p_;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200503 size_t len;
504 char *buf, modifier;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200505
Radek Krejcie534c132016-11-23 13:32:31 +0100506 /* init */
507 memset(&exts, 0, sizeof exts);
508
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200509 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100510 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200511 if (!value) {
512 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200513 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200514
515 i = parse_identifier(value);
516 if (i < 1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100517 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100518 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200519 goto error;
520 }
521 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100522 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200523 if (value[i]) {
524 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100525 name += i;
526 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100527 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100528 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200529 goto error;
530 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200531 /* name is in dictionary, but moved */
Radek Krejci225376f2016-02-16 17:36:22 +0100532 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200533 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200534
Radek Krejci225376f2016-02-16 17:36:22 +0100535 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200536 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100537 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200538 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200539 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100540
541 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200542 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200543 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200544 lydict_remove(module->ctx, value);
Radek Krejcidc008d72016-02-17 13:12:14 +0100545 ret = EXIT_FAILURE;
546 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200547 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200548 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200549
Radek Krejci9b6aad22016-09-20 15:55:51 +0200550 if (type->base == LY_TYPE_ERR) {
Radek Krejcic13db382016-08-16 10:52:42 +0200551 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Radek Krejci9b6aad22016-09-20 15:55:51 +0200552 * 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 +0200553 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
554 if (siter) {
Radek Krejci6ff885d2017-01-03 14:06:22 +0100555#if __BYTE_ORDER == __LITTLE_ENDIAN
556 if (!((uint8_t*)&((struct lys_node_grp *)siter)->flags)[1]) {
Radek Krejcic13db382016-08-16 10:52:42 +0200557 LOGINT;
558 goto error;
559 }
Radek Krejci6ff885d2017-01-03 14:06:22 +0100560 ((uint8_t*)&((struct lys_node_grp *)siter)->flags)[1]--;
561#else
562 if (!((uint8_t*)&((struct lys_node_grp *)siter)->flags)[0]) {
563 LOGINT;
564 goto error;
565 }
566 ((uint8_t*)&((struct lys_node_grp *)siter)->flags)[0]--;
567#endif
Radek Krejcic13db382016-08-16 10:52:42 +0200568 } else {
569 LOGINT;
570 goto error;
571 }
572 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200573 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200574
Radek Krejcicf509982015-12-15 09:22:44 +0100575 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100576 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejci48464ed2016-03-17 15:44:09 +0100577 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100578 return -1;
579 }
580
Radek Krejcie534c132016-11-23 13:32:31 +0100581 /* parse extension instances */
582 LY_TREE_FOR_SAFE(yin->child, next, node) {
583 if (!node->ns) {
584 /* garbage */
585 lyxml_free(module->ctx, node);
586 continue;
587 } else if (!strcmp(node->ns->value, LY_NSYIN)) {
588 /* YANG (YIN) statements - process later */
589 continue;
590 }
591
592 lyxml_unlink_elem(module->ctx, node, 2);
593 lyxml_add_child(module->ctx, &exts, node);
594 c_ext++;
595 }
596 if (c_ext) {
597 type->ext = calloc(c_ext, sizeof *type->ext);
598 if (!type->ext) {
599 LOGMEM;
600 goto error;
601 }
602 LY_TREE_FOR_SAFE(exts.child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +0100603 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 +0100604 type->ext_size++;
605 if (rc) {
606 goto error;
607 }
608 }
609 }
610
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200611 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200612 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200613 /* RFC 6020 9.7.4 - bit */
614
615 /* get bit specifications, at least one must be present */
616 LY_TREE_FOR_SAFE(yin->child, next, node) {
617 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200618 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200619 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100620 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200621 type->info.bits.count = 0;
Radek Krejci41726f92015-06-19 13:11:05 +0200622 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200623 }
624 }
Radek Krejcie663e012016-08-01 17:12:34 +0200625 dertype = &type->der->type;
626 if (!dertype->der) {
627 if (!type->info.bits.count) {
628 /* type is derived directly from buit-in bits type and bit statement is required */
629 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
630 goto error;
631 }
632 } else {
633 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
634 if (module->version < 2 && type->info.bits.count) {
635 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
636 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
637 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejci69794c62016-08-02 11:01:21 +0200638 type->info.bits.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200639 goto error;
640 }
Radek Krejciac781922015-07-09 15:35:14 +0200641 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200642
643 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100644 if (!type->info.bits.bit) {
645 LOGMEM;
646 goto error;
647 }
Radek Krejci73adb602015-07-02 18:07:40 +0200648 p = 0;
649 i = -1;
650 LY_TREE_FOR(yin->child, next) {
651 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200652 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200653
654 GETVAL(value, next, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100655 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100656 goto error;
657 }
658
Radek Krejci994b6f62015-06-18 16:47:27 +0200659 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100660 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 +0200661 type->info.bits.count = i + 1;
662 goto error;
663 }
664
Radek Krejcie663e012016-08-01 17:12:34 +0200665 if (!dertype->der) { /* directly derived type from bits built-in type */
666 /* check the name uniqueness */
667 for (j = 0; j < i; j++) {
668 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
669 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
670 type->info.bits.count = i + 1;
671 goto error;
672 }
673 }
674 } else {
675 /* restricted bits type - the name MUST be used in the base type */
676 bits_sc = dertype->info.bits.bit;
677 for (j = 0; j < dertype->info.bits.count; j++) {
678 if (ly_strequal(bits_sc[j].name, value, 1)) {
679 break;
680 }
681 }
682 if (j == dertype->info.bits.count) {
683 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci994b6f62015-06-18 16:47:27 +0200684 type->info.bits.count = i + 1;
685 goto error;
686 }
687 }
688
Radek Krejcie663e012016-08-01 17:12:34 +0200689
Radek Krejci0d70c372015-07-02 16:23:10 +0200690 p_ = -1;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100691 LY_TREE_FOR_SAFE(next->child, next2, node) {
692 if (!node->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200693 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200694 continue;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100695 } else if (strcmp(node->ns->value, LY_NSYIN)) {
696 /* extension */
697 if (read_yin_subnode_ext(module, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, node,
698 LYEXT_SUBSTMT_SELF, 0, unres)) {
699 goto error;
700 }
701 } else if (!strcmp(node->name, "position")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200702 if (p_ != -1) {
703 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
704 type->info.bits.count = i + 1;
705 goto error;
706 }
707
Radek Krejci0d70c372015-07-02 16:23:10 +0200708 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200709 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200710
711 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200712 if (p_ < 0 || p_ > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100713 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200714 type->info.bits.count = i + 1;
715 goto error;
716 }
717 type->info.bits.bit[i].pos = (uint32_t)p_;
718
Radek Krejcie663e012016-08-01 17:12:34 +0200719 if (!dertype->der) { /* directly derived type from bits built-in type */
720 /* keep the highest enum value for automatic increment */
721 if (type->info.bits.bit[i].pos >= p) {
722 p = type->info.bits.bit[i].pos;
723 p++;
724 } else {
725 /* check that the value is unique */
726 for (j = 0; j < i; j++) {
727 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
728 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
729 type->info.bits.bit[i].pos, type->info.bits.bit[i].name,
730 type->info.bits.bit[j].name);
731 type->info.bits.count = i + 1;
732 goto error;
733 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200734 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200735 }
736 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200737
Radek Krejci9b15fea2017-01-23 11:31:43 +0100738 if (read_yin_subnode_ext(module, &type->info.bits.bit[i], LYEXT_PAR_TYPE_BIT, node,
739 LYEXT_SUBSTMT_POSITION, 0, unres)) {
740 goto error;
741 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200742 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
743 c_ftrs++;
Radek Krejci0d70c372015-07-02 16:23:10 +0200744 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100745 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200746 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200747 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200748 }
Radek Krejcie663e012016-08-01 17:12:34 +0200749
750 if (!dertype->der) { /* directly derived type from bits built-in type */
751 if (p_ == -1) {
752 /* assign value automatically */
753 if (p > UINT32_MAX) {
754 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
755 type->info.bits.count = i + 1;
756 goto error;
757 }
758 type->info.bits.bit[i].pos = (uint32_t)p;
759 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
760 p++;
Radek Krejci994b6f62015-06-18 16:47:27 +0200761 }
Radek Krejcie663e012016-08-01 17:12:34 +0200762 } else { /* restricted bits type */
763 if (p_ == -1) {
764 /* automatically assign position from base type */
765 type->info.bits.bit[i].pos = bits_sc[j].pos;
766 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
767 } else {
768 /* check that the assigned position corresponds to the original
769 * position of the bit in the base type */
770 if (p_ != bits_sc[j].pos) {
771 /* p_ - assigned position in restricted bits
772 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
773 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
Radek Krejci541a45d2016-08-02 13:12:07 +0200774 type->info.bits.bit[i].name, bits_sc[j].pos);
Radek Krejcie663e012016-08-01 17:12:34 +0200775 type->info.bits.count = i + 1;
776 goto error;
777 }
778 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200779 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200780
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200781 /* if-features */
782 if (c_ftrs) {
783 bits_sc = &type->info.bits.bit[i];
784 bits_sc->iffeature = calloc(c_ftrs, sizeof *bits_sc->iffeature);
785 if (!bits_sc->iffeature) {
786 LOGMEM;
Radek Krejci994b6f62015-06-18 16:47:27 +0200787 type->info.bits.count = i + 1;
788 goto error;
789 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200790
791 LY_TREE_FOR(next->child, node) {
792 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +0200793 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200794 &bits_sc->iffeature[bits_sc->iffeature_size], unres);
795 bits_sc->iffeature_size++;
796 if (rc) {
797 type->info.bits.count = i + 1;
798 goto error;
799 }
800 }
801 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200802 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200803
804 /* keep them ordered by position */
805 j = i;
806 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
807 /* switch them */
808 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
809 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
810 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
811 j--;
812 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200813 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200814 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200815
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200816 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200817 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200818 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200819
Radek Krejcif9401c32015-06-26 16:47:36 +0200820 if (!strcmp(node->name, "range")) {
821 if (type->info.dec64.range) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100822 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200823 goto error;
824 }
825
826 GETVAL(value, node, "value");
Radek Krejcif9401c32015-06-26 16:47:36 +0200827 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100828 if (!type->info.dec64.range) {
829 LOGMEM;
830 goto error;
831 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200832 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
833
834 /* get possible substatements */
Radek Krejcifdc0d702017-01-23 15:58:38 +0100835 if (read_restr_substmt(module, LYEXT_PAR_RESTR, type->info.dec64.range, node, unres)) {
Radek Krejcif9401c32015-06-26 16:47:36 +0200836 goto error;
837 }
838 } else if (!strcmp(node->name, "fraction-digits")) {
839 if (type->info.dec64.dig) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100840 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200841 goto error;
842 }
843 GETVAL(value, node, "value");
844 v = strtol(value, NULL, 10);
845
846 /* range check */
847 if (v < 1 || v > 18) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100848 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200849 goto error;
850 }
851 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200852 type->info.dec64.div = 10;
853 for (i = 1; i < v; i++) {
854 type->info.dec64.div *= 10;
855 }
Radek Krejci47f7ea52017-01-23 13:14:09 +0100856
857 /* extensions */
858 if (read_yin_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_DIGITS, 0, unres)) {
859 goto error;
860 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200861 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100862 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200863 goto error;
864 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200865 }
866
867 /* mandatory sub-statement(s) check */
868 if (!type->info.dec64.dig && !type->der->type.der) {
869 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejci48464ed2016-03-17 15:44:09 +0100870 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200871 goto error;
872 }
Radek Krejci7511f402015-07-10 09:56:30 +0200873 if (type->info.dec64.dig && type->der->type.der) {
874 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100875 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200876 goto error;
877 }
Radek Krejci4800f652016-09-08 14:02:52 +0200878
879 /* copy fraction-digits specification from parent type for easier internal use */
880 if (type->der->type.der) {
881 type->info.dec64.dig = type->der->type.info.dec64.dig;
882 type->info.dec64.div = type->der->type.info.dec64.div;
883 }
884
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200885 if (type->info.dec64.range && lyp_check_length_range(type->info.dec64.range->expr, type)) {
886 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
887 goto error;
888 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200889 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200890
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200891 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200892 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200893
Radek Krejci994b6f62015-06-18 16:47:27 +0200894 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200895 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200896
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200897 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200898 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200899 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100900 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200901 type->info.enums.count = 0;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200902 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200903 }
904 }
Radek Krejcie663e012016-08-01 17:12:34 +0200905 dertype = &type->der->type;
906 if (!dertype->der) {
907 if (!type->info.enums.count) {
908 /* type is derived directly from buit-in enumeartion type and enum statement is required */
909 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
910 goto error;
911 }
912 } else {
913 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
914 if (module->version < 2 && type->info.enums.count) {
915 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
916 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
917 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejci69794c62016-08-02 11:01:21 +0200918 type->info.enums.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200919 goto error;
920 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200921 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200922
Radek Krejci1574a8d2015-08-03 14:16:52 +0200923 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100924 if (!type->info.enums.enm) {
925 LOGMEM;
926 goto error;
927 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200928
Radek Krejcie663e012016-08-01 17:12:34 +0200929 v = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200930 i = -1;
931 LY_TREE_FOR(yin->child, next) {
932 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200933 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200934
935 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100936 if (!value[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100937 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
938 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100939 goto error;
940 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200941 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci07d0fb92017-01-13 14:11:05 +0100942 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 +0200943 type->info.enums.count = i + 1;
944 goto error;
945 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200946
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200947 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200948 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200949 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100950 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200951 type->info.enums.count = i + 1;
952 goto error;
953 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200954
Radek Krejcie663e012016-08-01 17:12:34 +0200955 if (!dertype->der) { /* directly derived type from enumeration built-in type */
956 /* check the name uniqueness */
957 for (j = 0; j < i; j++) {
958 if (ly_strequal(type->info.enums.enm[j].name, value, 1)) {
959 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, value);
960 type->info.enums.count = i + 1;
961 goto error;
962 }
963 }
964 } else {
965 /* restricted enumeration type - the name MUST be used in the base type */
966 enms_sc = dertype->info.enums.enm;
967 for (j = 0; j < dertype->info.enums.count; j++) {
968 if (ly_strequal(enms_sc[j].name, value, 1)) {
969 break;
970 }
971 }
972 if (j == dertype->info.enums.count) {
973 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200974 type->info.enums.count = i + 1;
975 goto error;
976 }
977 }
Radek Krejci04581c62015-05-22 21:24:00 +0200978
Radek Krejcie663e012016-08-01 17:12:34 +0200979 val_set = 0;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100980 LY_TREE_FOR_SAFE(next->child, next2, node) {
981 if (!node->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200982 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200983 continue;
Radek Krejci9b15fea2017-01-23 11:31:43 +0100984 } else if (strcmp(node->ns->value, LY_NSYIN)) {
985 /* extensions */
986 if (read_yin_subnode_ext(module, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, node,
987 LYEXT_SUBSTMT_SELF, 0, unres)) {
988 goto error;
989 }
990 } else if (!strcmp(node->name, "value")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200991 if (val_set) {
992 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
993 type->info.enums.count = i + 1;
994 goto error;
995 }
996
Radek Krejci0d70c372015-07-02 16:23:10 +0200997 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200998 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200999
1000 /* range check */
1001 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001002 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +02001003 type->info.enums.count = i + 1;
1004 goto error;
1005 }
Radek Krejci1574a8d2015-08-03 14:16:52 +02001006 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +02001007
Radek Krejcie663e012016-08-01 17:12:34 +02001008 if (!dertype->der) { /* directly derived type from enumeration built-in type */
Pavol Vican5de389c2016-08-30 08:55:15 +02001009 if (!i) {
1010 /* change value, which is assigned automatically, if first enum has value. */
Radek Krejcie663e012016-08-01 17:12:34 +02001011 v = type->info.enums.enm[i].value;
1012 v++;
1013 } else {
Pavol Vican5de389c2016-08-30 08:55:15 +02001014 /* keep the highest enum value for automatic increment */
1015 if (type->info.enums.enm[i].value >= v) {
1016 v = type->info.enums.enm[i].value;
1017 v++;
1018 } else {
1019 /* check that the value is unique */
1020 for (j = 0; j < i; j++) {
1021 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
1022 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
1023 type->info.enums.enm[i].value, type->info.enums.enm[i].name,
1024 type->info.enums.enm[j].name);
1025 type->info.enums.count = i + 1;
1026 goto error;
1027 }
Radek Krejcie663e012016-08-01 17:12:34 +02001028 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001029 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001030 }
1031 }
Radek Krejcifc8d8322016-06-24 11:23:23 +02001032 val_set = 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001033
Radek Krejci9b15fea2017-01-23 11:31:43 +01001034 if (read_yin_subnode_ext(module, &type->info.enums.enm[i], LYEXT_PAR_TYPE_ENUM, node,
1035 LYEXT_SUBSTMT_VALUE, 0, unres)) {
1036 goto error;
1037 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001038 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
1039 c_ftrs++;
1040
Radek Krejci0d70c372015-07-02 16:23:10 +02001041 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001042 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001043 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001044 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001045 }
Radek Krejcie663e012016-08-01 17:12:34 +02001046
1047 if (!dertype->der) { /* directly derived type from enumeration */
1048 if (!val_set) {
1049 /* assign value automatically */
1050 if (v > INT32_MAX) {
1051 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
1052 type->info.enums.count = i + 1;
1053 goto error;
1054 }
1055 type->info.enums.enm[i].value = v;
1056 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1057 v++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001058 }
Radek Krejcie663e012016-08-01 17:12:34 +02001059 } else { /* restricted enum type */
1060 if (!val_set) {
1061 /* automatically assign value from base type */
1062 type->info.enums.enm[i].value = enms_sc[j].value;
1063 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
1064 } else {
1065 /* check that the assigned value corresponds to the original
1066 * value of the enum in the base type */
1067 if (v_ != enms_sc[j].value) {
1068 /* v_ - assigned value in restricted enum
1069 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
1070 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL,
Radek Krejci541a45d2016-08-02 13:12:07 +02001071 type->info.enums.enm[i].value, type->info.enums.enm[i].name, enms_sc[j].value);
Radek Krejcie663e012016-08-01 17:12:34 +02001072 type->info.enums.count = i + 1;
1073 goto error;
1074 }
1075 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001076 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001077
1078 /* if-features */
1079 if (c_ftrs) {
1080 enms_sc = &type->info.enums.enm[i];
1081 enms_sc->iffeature = calloc(c_ftrs, sizeof *enms_sc->iffeature);
1082 if (!enms_sc->iffeature) {
1083 LOGMEM;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001084 type->info.enums.count = i + 1;
1085 goto error;
1086 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001087
1088 LY_TREE_FOR(next->child, node) {
1089 if (!strcmp(node->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02001090 rc = fill_yin_iffeature((struct lys_node *)type->parent, 0, node,
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001091 &enms_sc->iffeature[enms_sc->iffeature_size], unres);
1092 enms_sc->iffeature_size++;
1093 if (rc) {
1094 type->info.enums.count = i + 1;
1095 goto error;
1096 }
1097 }
1098 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001099 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +02001100
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001101 }
1102 break;
1103
1104 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +02001105 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001106
Michal Vaskof2d43962016-09-02 11:10:16 +02001107 /* get base specification, at least one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +02001108 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001109
Michal Vaskoe29c6622015-11-27 15:02:31 +01001110 if (strcmp(node->name, "base")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001111 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001112 goto error;
1113 }
Michal Vaskof2d43962016-09-02 11:10:16 +02001114
1115 GETVAL(value, yin->child, "name");
1116 /* store in the JSON format */
1117 value = transform_schema2json(module, value);
1118 if (!value) {
1119 goto error;
1120 }
1121 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
1122 lydict_remove(module->ctx, value);
Michal Vaskof2d43962016-09-02 11:10:16 +02001123 if (rc == -1) {
1124 goto error;
1125 }
Radek Krejci18a44882017-01-23 13:47:29 +01001126
1127 if (read_yin_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_BASE, 0, unres)) {
1128 goto error;
1129 }
Radek Krejci0d70c372015-07-02 16:23:10 +02001130 }
1131
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001132 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +02001133 if (type->der->type.der) {
Michal Vaskof2d43962016-09-02 11:10:16 +02001134 /* this is just a derived type with no base required */
Radek Krejci65c889c2015-06-22 10:17:22 +02001135 break;
1136 }
Radek Krejci48464ed2016-03-17 15:44:09 +01001137 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001138 goto error;
Pavol Vicanf0046f42016-09-07 15:11:09 +02001139 } else {
1140 if (type->der->type.der) {
1141 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
1142 goto error;
1143 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001144 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001145 if (yin->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001146 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001147 goto error;
1148 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001149 break;
1150
1151 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +02001152 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +02001153 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001154
Radek Krejciaf351422015-06-19 14:49:38 +02001155 if (!strcmp(node->name, "require-instance")) {
1156 if (type->info.inst.req) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001157 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001158 goto error;
1159 }
1160 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001161 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001162 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +02001163 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +02001164 type->info.inst.req = -1;
1165 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001166 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001167 goto error;
1168 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001169
1170 /* extensions */
1171 if (read_yin_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINST, 0, unres)) {
1172 goto error;
1173 }
Radek Krejciaf351422015-06-19 14:49:38 +02001174 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001175 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +02001176 goto error;
1177 }
Radek Krejciaf351422015-06-19 14:49:38 +02001178 }
Michal Vasko8548cf92015-07-20 15:17:53 +02001179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001180 break;
1181
Radek Krejcif2860132015-06-20 12:37:20 +02001182 case LY_TYPE_BINARY:
1183 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001184 case LY_TYPE_INT8:
1185 case LY_TYPE_INT16:
1186 case LY_TYPE_INT32:
1187 case LY_TYPE_INT64:
1188 case LY_TYPE_UINT8:
1189 case LY_TYPE_UINT16:
1190 case LY_TYPE_UINT32:
1191 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +02001192 /* RFC 6020 9.2.4 - range */
1193
1194 /* length and range are actually the same restriction, so process
1195 * them by this common code, we just need to differ the name and
1196 * structure where the information will be stored
1197 */
1198 if (type->base == LY_TYPE_BINARY) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001199 restrs = &type->info.binary.length;
Radek Krejcif2860132015-06-20 12:37:20 +02001200 name = "length";
1201 } else {
Radek Krejcifccd1442017-01-16 10:26:57 +01001202 restrs = &type->info.num.range;
Radek Krejcif2860132015-06-20 12:37:20 +02001203 name = "range";
1204 }
1205
Radek Krejci73adb602015-07-02 18:07:40 +02001206 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001207
Radek Krejcif2860132015-06-20 12:37:20 +02001208 if (!strcmp(node->name, name)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001209 if (*restrs) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001210 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001211 goto error;
1212 }
1213
1214 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +02001215 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001216 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +02001217 goto error;
1218 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001219 *restrs = calloc(1, sizeof **restrs);
1220 if (!(*restrs)) {
Michal Vasko253035f2015-12-17 16:58:13 +01001221 LOGMEM;
1222 goto error;
1223 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001224 (*restrs)->expr = lydict_insert(module->ctx, value, 0);
Radek Krejcif2860132015-06-20 12:37:20 +02001225
1226 /* get possible substatements */
Radek Krejcifdc0d702017-01-23 15:58:38 +01001227 if (read_restr_substmt(module, LYEXT_PAR_RESTR, *restrs, node, unres)) {
Radek Krejcif2860132015-06-20 12:37:20 +02001228 goto error;
1229 }
1230 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001231 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001232 goto error;
1233 }
Radek Krejcif2860132015-06-20 12:37:20 +02001234 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001235 break;
1236
1237 case LY_TYPE_LEAFREF:
Radek Krejci3a5501d2016-07-18 22:03:34 +02001238 /* flag resolving for later use */
1239 if (!tpdftype) {
1240 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
1241 if (siter) {
1242 /* just a flag - do not resolve */
1243 tpdftype = 1;
1244 }
1245 }
1246
Radek Krejcidc4c1412015-06-19 15:39:54 +02001247 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +02001248 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001249
Michal Vasko88c29542015-11-27 14:57:53 +01001250 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +02001251 if (type->info.lref.path) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001252 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001253 goto error;
1254 }
1255
1256 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +02001257 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +01001258 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +02001259 if (!type->info.lref.path) {
1260 goto error;
1261 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001262
1263 /* try to resolve leafref path only when this is instantiated
1264 * leaf, so it is not:
1265 * - typedef's type,
1266 * - in grouping definition,
1267 * - just instantiated in a grouping definition,
1268 * because in those cases the nodes referenced in path might not be present
1269 * and it is not a bug. */
1270 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001271 goto error;
1272 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001273
1274 /* extensions */
1275 if (read_yin_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_PATH, 0, unres)) {
1276 goto error;
1277 }
Radek Krejcid6353ed2016-09-15 13:30:45 +02001278 } else if (module->version >= 2 && !strcmp(node->name, "require-instance")) {
Michal Vasko08ae53e2016-09-02 12:40:04 +02001279 if (type->info.lref.req) {
1280 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
1281 goto error;
1282 }
1283 GETVAL(value, node, "value");
1284 if (!strcmp(value, "true")) {
1285 type->info.lref.req = 1;
1286 } else if (!strcmp(value, "false")) {
1287 type->info.lref.req = -1;
1288 } else {
1289 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
1290 goto error;
1291 }
Radek Krejci47f7ea52017-01-23 13:14:09 +01001292
1293 /* extensions */
1294 if (read_yin_subnode_ext(module, type, LYEXT_PAR_TYPE, node, LYEXT_SUBSTMT_REQINST, 0, unres)) {
1295 goto error;
1296 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001297 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001298 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001299 goto error;
1300 }
Radek Krejci73adb602015-07-02 18:07:40 +02001301 }
1302
Radek Krejci742be352016-07-17 12:18:54 +02001303 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001304 if (!type->der->type.der) {
1305 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
1306 goto error;
1307 } else {
1308 /* copy leafref definition into the derived type */
1309 type->info.lref.path = lydict_insert(module->ctx, type->der->type.info.lref.path, 0);
1310 /* and resolve the path at the place we are (if not in grouping/typedef) */
1311 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
1312 goto error;
1313 }
1314
1315 /* add pointer to leafref target, only on leaves (not in typedefs) */
1316 if (type->info.lref.target && lys_leaf_add_leafref_target(type->info.lref.target, (struct lys_node *)type->parent)) {
1317 goto error;
1318 }
1319 }
Radek Krejci742be352016-07-17 12:18:54 +02001320 }
1321
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001322 break;
1323
1324 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +02001325 /* RFC 6020 9.4.4 - length */
1326 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +02001327 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +02001328 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001329
Radek Krejci3733a802015-06-19 13:43:21 +02001330 if (!strcmp(node->name, "length")) {
1331 if (type->info.str.length) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001332 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001333 goto error;
1334 }
1335
1336 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +02001337 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001338 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +02001339 goto error;
1340 }
1341 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +01001342 if (!type->info.str.length) {
1343 LOGMEM;
1344 goto error;
1345 }
Radek Krejci3733a802015-06-19 13:43:21 +02001346 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
1347
Radek Krejci5fbc9162015-06-19 14:11:11 +02001348 /* get possible sub-statements */
Radek Krejcifdc0d702017-01-23 15:58:38 +01001349 if (read_restr_substmt(module, LYEXT_PAR_RESTR, type->info.str.length, node, unres)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001350 goto error;
1351 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001352 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001353 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +02001354 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001355 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001356 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001357 goto error;
1358 }
1359 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001360 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001361 if (i) {
1362 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +01001363 if (!type->info.str.patterns) {
1364 LOGMEM;
1365 goto error;
1366 }
Radek Krejci73adb602015-07-02 18:07:40 +02001367 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +01001368 GETVAL(value, node, "value");
Michal Vasko0aee5c12016-06-17 14:27:26 +02001369 if (lyp_check_pattern(value, NULL)) {
Michal Vasko69068852015-07-13 14:34:31 +02001370 free(type->info.str.patterns);
Radek Krejci9f1e8532016-06-16 11:18:21 +02001371 type->info.str.patterns = NULL;
Michal Vasko69068852015-07-13 14:34:31 +02001372 goto error;
1373 }
Radek Krejcifccd1442017-01-16 10:26:57 +01001374 restr = &type->info.str.patterns[type->info.str.pat_count]; /* shortcut */
Michal Vasko69068852015-07-13 14:34:31 +02001375
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001376 modifier = 0x06; /* ACK */
1377 name = NULL;
Radek Krejcifccd1442017-01-16 10:26:57 +01001378 if (module->version >= 2) {
1379 LY_TREE_FOR_SAFE(node->child, next2, child) {
1380 if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
1381 if (name) {
1382 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
1383 goto error;
1384 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001385
Radek Krejcifccd1442017-01-16 10:26:57 +01001386 GETVAL(name, child, "value");
1387 if (!strcmp(name, "invert-match")) {
1388 modifier = 0x15; /* NACK */
1389 } else {
1390 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
1391 goto error;
1392 }
1393 /* get extensions of the modifier */
Radek Krejcifdc0d702017-01-23 15:58:38 +01001394 if (read_yin_subnode_ext(module, restr, LYEXT_PAR_RESTR, child,
Radek Krejciac00b2a2017-01-17 14:05:00 +01001395 LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01001396 return EXIT_FAILURE;
1397 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001398
Radek Krejcifccd1442017-01-16 10:26:57 +01001399 lyxml_free(module->ctx, child);
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001400 }
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001401 }
1402 }
1403
1404 len = strlen(value);
1405 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
1406 buf[0] = modifier;
1407 strcpy(&buf[1], value);
1408
Radek Krejcifccd1442017-01-16 10:26:57 +01001409 restr->expr = lydict_insert_zc(module->ctx, buf);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001410
1411 /* get possible sub-statements */
Radek Krejcifdc0d702017-01-23 15:58:38 +01001412 if (read_restr_substmt(module, LYEXT_PAR_RESTR, restr, node, unres)) {
Michal Vasko69068852015-07-13 14:34:31 +02001413 free(type->info.str.patterns);
Pavol Vican9fc5d642016-08-30 15:23:19 +02001414 type->info.str.patterns = NULL;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001415 goto error;
1416 }
Radek Krejci73adb602015-07-02 18:07:40 +02001417 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001418 }
1419 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001420 break;
1421
1422 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001423 /* RFC 6020 7.4 - type */
1424 /* count number of types in union */
1425 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001426 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001427
Radek Krejcie4c366b2015-07-02 10:11:31 +02001428 if (!strcmp(node->name, "type")) {
Radek Krejci038d5d92016-09-12 15:07:15 +02001429 if (type->der->type.der) {
1430 /* type can be a substatement only in "union" type, not in derived types */
1431 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "derived type");
1432 goto error;
1433 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001434 i++;
1435 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001436 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001437 goto error;
1438 }
1439 }
1440
Radek Krejci038d5d92016-09-12 15:07:15 +02001441 if (!i && !type->der->type.der) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001442 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001443 goto error;
1444 }
1445
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001446 /* inherit instid presence information */
1447 if ((type->der->type.base == LY_TYPE_UNION) && type->der->type.info.uni.has_ptr_type) {
1448 type->info.uni.has_ptr_type = 1;
1449 }
1450
Radek Krejcie4c366b2015-07-02 10:11:31 +02001451 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001452 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +01001453 if (!type->info.uni.types) {
1454 LOGMEM;
1455 goto error;
1456 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001457 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001458 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +01001459 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001460 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], tpdftype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +01001461 if (!rc) {
1462 type->info.uni.count++;
1463
Radek Krejci7de36cf2016-09-12 16:18:50 +02001464 if (module->version < 2) {
1465 /* union's type cannot be empty or leafref */
1466 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
1467 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
1468 rc = -1;
1469 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
1470 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
1471 rc = -1;
1472 }
Michal Vasko88c29542015-11-27 14:57:53 +01001473 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001474
1475 if ((type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_INST)
1476 || (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF)) {
1477 type->info.uni.has_ptr_type = 1;
1478 }
Michal Vasko88c29542015-11-27 14:57:53 +01001479 }
1480 if (rc) {
1481 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
1482 for (i = 0; i < type->info.uni.count; ++i) {
1483 lys_type_free(module->ctx, &type->info.uni.types[i]);
1484 }
1485 free(type->info.uni.types);
1486 type->info.uni.types = NULL;
1487 type->info.uni.count = 0;
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001488 type->info.uni.has_ptr_type = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +02001489 type->der = NULL;
1490 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +01001491
1492 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +01001493 ret = EXIT_FAILURE;
Michal Vasko88c29542015-11-27 14:57:53 +01001494 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001495 goto error;
1496 }
Michal Vasko88c29542015-11-27 14:57:53 +01001497 }
1498 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001499
Michal Vasko88c29542015-11-27 14:57:53 +01001500 case LY_TYPE_BOOL:
1501 case LY_TYPE_EMPTY:
1502 /* no sub-statement allowed */
Radek Krejcie534c132016-11-23 13:32:31 +01001503 if (yin->child) {
1504 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->child->name);
1505 goto error;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001506 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001507 break;
1508
1509 default:
Michal Vasko88c29542015-11-27 14:57:53 +01001510 LOGINT;
1511 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001512 }
1513
1514 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001515
1516error:
Radek Krejcidc008d72016-02-17 13:12:14 +01001517 if (type->module_name) {
1518 lydict_remove(module->ctx, type->module_name);
1519 type->module_name = NULL;
1520 }
Radek Krejcie534c132016-11-23 13:32:31 +01001521 lyxml_free_withsiblings(module->ctx, exts.child);
1522
Radek Krejcidc008d72016-02-17 13:12:14 +01001523 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001524}
1525
Michal Vasko0d343d12015-08-24 14:57:36 +02001526/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001527static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01001528fill_yin_typedef(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_tpdf *tpdf,
1529 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001530{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001531 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +01001532 struct lyxml_elem *node, *next;
Radek Krejcie534c132016-11-23 13:32:31 +01001533 int rc, has_type = 0, c_ext = 0;
Radek Krejci59a349f2017-01-24 10:14:31 +01001534 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001535
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001536 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001537 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001538 goto error;
1539 }
1540 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001541
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001542 /* generic part - status, description, reference */
Radek Krejci07d0fb92017-01-13 14:11:05 +01001543 if (read_yin_common(module, NULL, tpdf, LYEXT_PAR_TPDF, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001544 goto error;
1545 }
Radek Krejcieac35532015-05-31 19:09:15 +02001546
Michal Vasko88c29542015-11-27 14:57:53 +01001547 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejcie534c132016-11-23 13:32:31 +01001548 if (strcmp(node->ns->value, LY_NSYIN)) {
1549 /* extension */
1550 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02001551 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01001552 } else if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001553 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001554 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001555 goto error;
1556 }
Michal Vasko88c29542015-11-27 14:57:53 +01001557 /* HACK for unres */
1558 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001559 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001560 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001561 goto error;
1562 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001563 has_type = 1;
Radek Krejcie534c132016-11-23 13:32:31 +01001564
Radek Krejci07d0fb92017-01-13 14:11:05 +01001565 /* 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 +01001566 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001567 } else if (!strcmp(node->name, "default")) {
1568 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001569 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001570 goto error;
1571 }
1572 GETVAL(value, node, "value");
1573 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001574
1575 if (read_yin_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
1576 goto error;
1577 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001578 } else if (!strcmp(node->name, "units")) {
1579 if (tpdf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001580 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001581 goto error;
1582 }
1583 GETVAL(value, node, "name");
1584 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci59a349f2017-01-24 10:14:31 +01001585
1586 if (read_yin_subnode_ext(module, tpdf, LYEXT_PAR_TPDF, node, LYEXT_SUBSTMT_UNITS, 0, unres)) {
1587 goto error;
1588 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001589 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001590 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001591 goto error;
1592 }
Radek Krejcie534c132016-11-23 13:32:31 +01001593
1594 lyxml_free(module->ctx, node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001595 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001596
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001597 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001598 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001599 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001600 goto error;
1601 }
Radek Krejcieac35532015-05-31 19:09:15 +02001602
Michal Vasko478c4652016-07-21 12:55:01 +02001603 /* check default value (if not defined, there still could be some restrictions
1604 * that need to be checked against a default value from a derived type) */
Radek Krejci51673202016-11-01 17:00:32 +01001605 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&tpdf->dflt)) == -1) {
Michal Vasko478c4652016-07-21 12:55:01 +02001606 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001607 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001608
Radek Krejcie534c132016-11-23 13:32:31 +01001609 /* finish extensions parsing */
1610 if (c_ext) {
Radek Krejci59a349f2017-01-24 10:14:31 +01001611 /* some extensions may be already present from the substatements */
1612 reallocated = realloc(tpdf->ext, (c_ext + tpdf->ext_size) * sizeof *tpdf->ext);
1613 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01001614 LOGMEM;
1615 goto error;
1616 }
Radek Krejci59a349f2017-01-24 10:14:31 +01001617 tpdf->ext = reallocated;
1618
1619 /* init memory */
1620 memset(&tpdf->ext[tpdf->ext_size], 0, c_ext * sizeof *tpdf->ext);
1621
Radek Krejcie534c132016-11-23 13:32:31 +01001622 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001623 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 +01001624 tpdf->ext_size++;
1625 if (rc) {
1626 goto error;
1627 }
1628 }
1629 }
1630
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001631 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001632
1633error:
1634
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001635 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001636}
1637
Radek Krejcia1a6b762016-11-14 09:53:38 +09001638static int
Radek Krejcie534c132016-11-23 13:32:31 +01001639fill_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 +09001640{
1641 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01001642 struct lyxml_elem *child, *node, *next, *next2;
1643 int c_ext = 0, rc;
Radek Krejci1fb02182017-01-24 11:20:55 +01001644 void *reallocated;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001645
1646 GETVAL(value, yin, "name");
1647
1648 if (lyp_check_identifier(value, LY_IDENT_EXTENSION, module, NULL)) {
1649 goto error;
1650 }
1651 ext->name = lydict_insert(module->ctx, value, strlen(value));
1652
Radek Krejci07d0fb92017-01-13 14:11:05 +01001653 if (read_yin_common(module, NULL, ext, LYEXT_PAR_EXT, yin, OPT_MODULE, unres)) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09001654 goto error;
1655 }
1656
Radek Krejcie534c132016-11-23 13:32:31 +01001657 LY_TREE_FOR_SAFE(yin->child, next, node) {
1658 if (strcmp(node->ns->value, LY_NSYIN)) {
1659 /* possible extension instance */
1660 c_ext++;
1661 } else if (!strcmp(node->name, "argument")) {
1662 /* argument */
1663 GETVAL(value, node, "name");
1664 ext->argument = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci1fb02182017-01-24 11:20:55 +01001665 if (read_yin_subnode_ext(module, ext, LYEXT_PAR_EXT, node, LYEXT_SUBSTMT_ARGUMENT, 0, unres)) {
1666 goto error;
1667 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09001668
Radek Krejcia1a6b762016-11-14 09:53:38 +09001669 /* yin-element */
Radek Krejcie534c132016-11-23 13:32:31 +01001670 LY_TREE_FOR_SAFE(node->child, next2, child) {
1671 if (child->ns == node->ns && !strcmp(child->name, "yin-element")) {
1672 GETVAL(value, child, "value");
1673 if (ly_strequal(value, "true", 0)) {
1674 ext->flags |= LYS_YINELEM;
1675 }
Radek Krejci1fb02182017-01-24 11:20:55 +01001676
1677 if (read_yin_subnode_ext(module, ext, LYEXT_PAR_EXT, child, LYEXT_SUBSTMT_YINELEM, 0, unres)) {
1678 goto error;
1679 }
Radek Krejcie534c132016-11-23 13:32:31 +01001680 } else if (child->ns) {
1681 /* unexpected YANG statement */
1682 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->name);
1683 goto error;
1684 } /* else garbage, but save resource needed for unlinking */
Radek Krejcia1a6b762016-11-14 09:53:38 +09001685 }
1686
Radek Krejcie534c132016-11-23 13:32:31 +01001687 lyxml_free(module->ctx, node);
1688 } else {
1689 /* unexpected YANG statement */
1690 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, node->name, node->name);
1691 goto error;
1692 }
1693 }
1694
1695 if (c_ext) {
Radek Krejci1fb02182017-01-24 11:20:55 +01001696 /* some extensions may be already present from the substatements */
1697 reallocated = realloc(ext->ext, (c_ext + ext->ext_size) * sizeof *ext->ext);
1698 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01001699 LOGMEM;
1700 goto error;
1701 }
Radek Krejci1fb02182017-01-24 11:20:55 +01001702 ext->ext = reallocated;
1703
1704 /* init memory */
1705 memset(&ext->ext[ext->ext_size], 0, c_ext * sizeof *ext->ext);
1706
1707 /* process the extension instances of the extension itself */
Radek Krejcie534c132016-11-23 13:32:31 +01001708 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci2b999ac2017-01-18 16:22:12 +01001709 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 +01001710 ext->ext_size++;
1711 if (rc) {
1712 goto error;
Radek Krejcia1a6b762016-11-14 09:53:38 +09001713 }
1714 }
1715 }
1716
Radek Krejci0a498f82017-01-04 16:24:15 +01001717 /* search for plugin */
1718 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 +09001719
1720 return EXIT_SUCCESS;
1721
1722error:
1723 return EXIT_FAILURE;
1724}
1725
Michal Vasko0d343d12015-08-24 14:57:36 +02001726/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001727static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001728fill_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 +02001729{
1730 const char *value;
1731 struct lyxml_elem *child, *next;
Radek Krejcie534c132016-11-23 13:32:31 +01001732 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci5323b492017-01-16 15:40:11 +01001733 void *reallocated;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001734
Radek Krejcib05774c2015-06-18 13:52:59 +02001735 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001736 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001737 goto error;
1738 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001739 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001740 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001741
Radek Krejci07d0fb92017-01-13 14:11:05 +01001742 if (read_yin_common(module, NULL, f, LYEXT_PAR_FEATURE, yin, 0, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001743 goto error;
1744 }
1745
Radek Krejcie534c132016-11-23 13:32:31 +01001746 LY_TREE_FOR(yin->child, child) {
1747 if (strcmp(child->ns->value, LY_NSYIN)) {
1748 /* extension */
1749 c_ext++;
1750 } else if (!strcmp(child->name, "if-feature")) {
1751 c_ftrs++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001752 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001753 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001754 goto error;
1755 }
1756 }
1757
Radek Krejcie534c132016-11-23 13:32:31 +01001758 if (c_ftrs) {
1759 f->iffeature = calloc(c_ftrs, sizeof *f->iffeature);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001760 if (!f->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01001761 LOGMEM;
1762 goto error;
1763 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001764 }
Radek Krejcie534c132016-11-23 13:32:31 +01001765 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01001766 /* some extensions may be already present from the substatements */
1767 reallocated = realloc(f->ext, (c_ext + f->ext_size) * sizeof *f->ext);
1768 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01001769 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001770 goto error;
1771 }
Radek Krejci5323b492017-01-16 15:40:11 +01001772 f->ext = reallocated;
1773
1774 /* init memory */
1775 memset(&f->ext[f->ext_size], 0, c_ext * sizeof *f->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001776 }
1777
Radek Krejcie534c132016-11-23 13:32:31 +01001778 LY_TREE_FOR_SAFE(yin->child, next, child) {
1779 if (strcmp(child->ns->value, LY_NSYIN)) {
1780 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01001781 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 +01001782 f->ext_size++;
1783 if (ret) {
1784 goto error;
1785 }
1786 } else { /* if-feature */
1787 ret = fill_yin_iffeature((struct lys_node *)f, 1, child, &f->iffeature[f->iffeature_size], unres);
1788 f->iffeature_size++;
1789 if (ret) {
1790 goto error;
1791 }
1792 }
1793 }
1794
Radek Krejcic79c6b12016-07-26 15:11:49 +02001795 /* check for circular dependencies */
1796 if (f->iffeature_size) {
1797 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1798 goto error;
1799 }
1800 }
1801
Radek Krejci3cf9e222015-06-18 11:37:50 +02001802 return EXIT_SUCCESS;
1803
1804error:
1805
1806 return EXIT_FAILURE;
1807}
1808
Michal Vasko0d343d12015-08-24 14:57:36 +02001809/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001810static int
Radek Krejcifccd1442017-01-16 10:26:57 +01001811fill_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 +02001812{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001813 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001814
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001815 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001816 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001817 if (!must->expr) {
1818 goto error;
1819 }
Radek Krejci800af702015-06-02 13:46:01 +02001820
Radek Krejcifdc0d702017-01-23 15:58:38 +01001821 return read_restr_substmt(module, LYEXT_PAR_RESTR, must, yin, unres);
Radek Krejci800af702015-06-02 13:46:01 +02001822
Michal Vasko77dc5652016-02-15 12:32:42 +01001823error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001824 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001825}
1826
Radek Krejci581ce772015-11-10 17:22:40 +01001827static int
Michal Vasko88c29542015-11-27 14:57:53 +01001828fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1829 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001830{
1831 int i, j;
1832 const char *value, *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +02001833 struct unres_list_uniq *unique_info;
Radek Krejci581ce772015-11-10 17:22:40 +01001834
1835 /* get unique value (list of leafs supposed to be unique */
1836 GETVAL(value, yin, "tag");
1837
1838 /* count the number of unique leafs in the value */
1839 vaux = value;
1840 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001841 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001842 while (isspace(*vaux)) {
1843 vaux++;
1844 }
1845 }
1846 unique->expr_size++;
1847 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001848 if (!unique->expr) {
1849 LOGMEM;
1850 goto error;
1851 }
Radek Krejci581ce772015-11-10 17:22:40 +01001852
1853 for (i = 0; i < unique->expr_size; i++) {
1854 vaux = strpbrk(value, " \t\n");
1855 if (!vaux) {
1856 /* the last token, lydict_insert() will count its size on its own */
1857 vaux = value;
1858 }
1859
1860 /* store token into unique structure */
1861 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1862
1863 /* check that the expression does not repeat */
1864 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001865 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001866 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1867 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001868 goto error;
1869 }
1870 }
1871
1872 /* try to resolve leaf */
1873 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001874 unique_info = malloc(sizeof *unique_info);
1875 unique_info->list = parent;
1876 unique_info->expr = unique->expr[i];
1877 unique_info->trg_type = &unique->trg_type;
1878 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1){
Pavol Vican18b10212016-04-11 15:41:52 +02001879 goto error;
1880 }
Radek Krejci581ce772015-11-10 17:22:40 +01001881 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001882 if (resolve_unique(parent, unique->expr[i], &unique->trg_type)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001883 goto error;
1884 }
1885 }
1886
1887 /* move to next token */
1888 value = vaux;
1889 while(isspace(*value)) {
1890 value++;
1891 }
1892 }
1893
1894 return EXIT_SUCCESS;
1895
1896error:
1897 return EXIT_FAILURE;
1898}
1899
Michal Vasko0d343d12015-08-24 14:57:36 +02001900/* logs directly
1901 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001902 * type: 0 - min, 1 - max
1903 */
1904static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001905deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001906{
1907 const char *value;
1908 char *endptr;
1909 unsigned long val;
Pavol Vican09adcc32016-08-25 10:51:36 +02001910 uint32_t *ui32val, *min, *max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001911
Michal Vaskof7e57d52016-03-07 11:31:09 +01001912 /* del min/max is forbidden */
1913 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001914 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001915 goto error;
1916 }
1917
Radek Krejcieb00f512015-07-01 16:44:58 +02001918 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001919 if (target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001920 max = &((struct lys_node_leaflist *)target)->max;
1921 min = &((struct lys_node_leaflist *)target)->min;
Radek Krejci76512572015-08-04 09:47:08 +02001922 } else if (target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001923 max = &((struct lys_node_list *)target)->max;
1924 min = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001925 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001926 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1927 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001928 goto error;
1929 }
1930
1931 GETVAL(value, node, "value");
1932 while (isspace(value[0])) {
1933 value++;
1934 }
1935
Radek Krejci0d7b2472016-02-12 11:11:03 +01001936 if (type && !strcmp(value, "unbounded")) {
1937 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001938 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001939 ui32val = max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001940 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001941 /* convert it to uint32_t */
1942 errno = 0;
1943 endptr = NULL;
1944 val = strtoul(value, &endptr, 10);
1945 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001946 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001947 goto error;
1948 }
1949 if (type) {
1950 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001951 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001952 ui32val = max;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001953 } else {
1954 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001955 d->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001956 ui32val = min;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001957 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001958 }
1959
1960 if (d->mod == LY_DEVIATE_ADD) {
1961 /* check that there is no current value */
1962 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001963 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1964 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001965 goto error;
1966 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001967 } else if (d->mod == LY_DEVIATE_RPL) {
1968 /* unfortunately, there is no way to check reliably that there
1969 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02001970 }
1971
Michal Vaskof7e57d52016-03-07 11:31:09 +01001972 /* add (already checked) and replace */
1973 /* set new value specified in deviation */
1974 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02001975
Pavol Vican09adcc32016-08-25 10:51:36 +02001976 /* check min-elements is smaller than max-elements */
1977 if (*max && *min > *max) {
1978 if (type) {
Radek Krejci73f96012016-10-03 13:53:53 +02001979 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "max-elements");
Pavol Vican09adcc32016-08-25 10:51:36 +02001980 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
1981 } else {
Radek Krejci73f96012016-10-03 13:53:53 +02001982 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "min-elements");
Pavol Vican09adcc32016-08-25 10:51:36 +02001983 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
1984 }
1985 goto error;
1986 }
1987
Radek Krejcieb00f512015-07-01 16:44:58 +02001988 return EXIT_SUCCESS;
1989
1990error:
1991
1992 return EXIT_FAILURE;
1993}
1994
Michal Vasko0d343d12015-08-24 14:57:36 +02001995/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001996static int
Michal Vasko88c29542015-11-27 14:57:53 +01001997fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1998 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001999{
2000 const char *value, **stritem;
Radek Krejcie534c132016-11-23 13:32:31 +01002001 struct lyxml_elem *next, *next2, *child, *develem;
2002 int c_dev = 0, c_must, c_uniq, c_dflt, c_ext = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002003 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01002004 int i, j, rc;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002005 unsigned int u;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002006 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02002007 struct lys_deviate *d = NULL;
Radek Krejcie00d2312016-08-12 15:27:49 +02002008 struct lys_node *node = NULL, *parent, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002009 struct lys_node_choice *choice = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002010 struct lys_node_leaf *leaf = NULL;
2011 struct ly_set *dflt_check = ly_set_new();
Radek Krejcib8048692015-08-05 13:36:34 +02002012 struct lys_node_list *list = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002013 struct lys_node_leaflist *llist = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002014 struct lys_type *t = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002015 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02002016 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01002017 struct unres_schema tmp_unres;
Radek Krejci27fe55e2016-09-13 17:13:35 +02002018 struct lys_module *mod;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002019 void *reallocated;
Radek Krejcieb00f512015-07-01 16:44:58 +02002020
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002021 ctx = module->ctx;
2022
Radek Krejcieb00f512015-07-01 16:44:58 +02002023 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002024 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002025 if (!dev->target_name) {
2026 goto error;
2027 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002028
2029 /* resolve target node */
Radek Krejcidf46e222016-11-08 11:57:37 +01002030 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1, (const struct lys_node **)&dev_target);
Michal Vasko60f4b452016-02-12 11:02:55 +01002031 if (rc || !dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002032 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002033 goto error;
2034 }
Radek Krejcic4283442016-04-22 09:19:27 +02002035 if (dev_target->module == lys_main_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002036 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
2037 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002038 goto error;
2039 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002040
2041 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01002042 if (!child->ns ) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002043 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002044 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002045 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01002046 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2047 /* extension */
2048 c_ext++;
2049 continue;
2050 } else if (!strcmp(child->name, "description")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002051 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002052 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002053 goto error;
2054 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002055 if (read_yin_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
2056 goto error;
2057 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002058 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002059 if (!dev->dsc) {
2060 goto error;
2061 }
2062 } else if (!strcmp(child->name, "reference")) {
2063 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002064 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002065 goto error;
2066 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002067 if (read_yin_subnode_ext(module, dev, LYEXT_PAR_DEVIATION, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
2068 goto error;
2069 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002070 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02002071 if (!dev->ref) {
2072 goto error;
2073 }
2074 } else if (!strcmp(child->name, "deviate")) {
2075 c_dev++;
2076
Michal Vasko345da0a2015-12-02 10:35:55 +01002077 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02002078 * further processed later
2079 */
2080 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02002081
Radek Krejcieb00f512015-07-01 16:44:58 +02002082 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002083 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002084 goto error;
2085 }
2086
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002087 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02002088 }
2089
2090 if (c_dev) {
2091 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01002092 if (!dev->deviate) {
2093 LOGMEM;
2094 goto error;
2095 }
Pavol Vican09adcc32016-08-25 10:51:36 +02002096 } else {
2097 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
2098 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002099 }
Radek Krejcie534c132016-11-23 13:32:31 +01002100 if (c_ext) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002101 /* some extensions may be already present from the substatements */
2102 reallocated = realloc(dev->ext, (c_ext + dev->ext_size) * sizeof *dev->ext);
2103 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01002104 LOGMEM;
2105 goto error;
2106 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002107 dev->ext = reallocated;
Radek Krejcieb00f512015-07-01 16:44:58 +02002108
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002109 /* init memory */
2110 memset(&dev->ext[dev->ext_size], 0, c_ext * sizeof *dev->ext);
2111 }
Radek Krejcie534c132016-11-23 13:32:31 +01002112
2113 LY_TREE_FOR_SAFE(yin->child, next, develem) {
2114 if (strcmp(develem->ns->value, LY_NSYIN)) {
2115 /* deviation's extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01002116 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 +01002117 dev->ext_size++;
2118 if (rc) {
2119 goto error;
2120 }
2121 continue;
2122 }
2123
2124 /* deviate */
Radek Krejcieb00f512015-07-01 16:44:58 +02002125 /* init */
2126 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01002127 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002128 c_must = 0;
2129 c_uniq = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002130 c_dflt = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01002131 c_ext = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02002132
2133 /* get deviation type */
2134 GETVAL(value, develem, "value");
2135 if (!strcmp(value, "not-supported")) {
2136 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002137 /* no other deviate statement is expected,
Radek Krejci5b917642015-07-02 09:03:13 +02002138 * not-supported deviation must be the only deviation of the target
2139 */
2140 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002141 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2142 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02002143 goto error;
2144 }
2145
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002146 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02002147 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
2148 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
2149 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002150 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
2151 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01002152 goto error;
2153 }
2154 }
2155 }
Radek Krejci5b917642015-07-02 09:03:13 +02002156
Michal Vaskoff006c12016-02-17 11:15:19 +01002157 /* unlink and store the original node */
2158 lys_node_unlink(dev_target);
2159 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02002160
Radek Krejcieb00f512015-07-01 16:44:58 +02002161 } else if (!strcmp(value, "add")) {
2162 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
2163 } else if (!strcmp(value, "replace")) {
2164 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
2165 } else if (!strcmp(value, "delete")) {
2166 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
2167 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002168 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002169 goto error;
2170 }
2171 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01002172 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002173
Michal Vaskoff006c12016-02-17 11:15:19 +01002174 /* store a shallow copy of the original node */
2175 if (!dev->orig_node) {
2176 memset(&tmp_unres, 0, sizeof tmp_unres);
Radek Krejci6ff885d2017-01-03 14:06:22 +01002177 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, &tmp_unres, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01002178 /* just to be safe */
2179 if (tmp_unres.count) {
2180 LOGINT;
2181 goto error;
2182 }
2183 }
2184
Radek Krejcieb00f512015-07-01 16:44:58 +02002185 /* process deviation properties */
Radek Krejcie534c132016-11-23 13:32:31 +01002186 LY_TREE_FOR_SAFE(develem->child, next2, child) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002187 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002188 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002189 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002190 continue;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002191 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2192 /* extensions */
2193 c_ext++;
2194 } else if (d->mod == LY_DEVIATE_NO) {
2195 /* no YIN substatement expected in this case */
2196 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2197 goto error;
2198 } else if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002199 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002200 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002201 goto error;
2202 }
2203
2204 /* for we deviate from RFC 6020 and allow config property even it is/is not
2205 * specified in the target explicitly since config property inherits. So we expect
2206 * that config is specified in every node. But for delete, we check that the value
2207 * is the same as here in deviation
2208 */
2209 GETVAL(value, child, "value");
2210 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002211 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02002212 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002213 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02002214 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002215 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002216 goto error;
2217 }
2218
2219 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002220 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002221 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002222 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002223 } else { /* add and replace are the same in this case */
2224 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01002225 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002226
2227 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01002228 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002229 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002230
2231 if (read_yin_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
2232 goto error;
2233 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002234 } else if (!strcmp(child->name, "default")) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002235 if (read_yin_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_DEFAULT, c_dflt, unres)) {
2236 goto error;
2237 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002238 c_dflt++;
2239
2240 /* check target node type */
2241 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
2242 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2243 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
2244 goto error;
2245 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
2246 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2247 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
2248 goto error;
2249 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
2250 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2251 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002252 goto error;
2253 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002254
Radek Krejcid5a5c282016-08-15 15:38:08 +02002255 /* skip lyxml_free() at the end of the loop, this node will be processed later */
2256 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02002257
Radek Krejcieb00f512015-07-01 16:44:58 +02002258 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002259 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002260 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002261 goto error;
2262 }
2263
2264 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002265 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002266 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2267 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002268 goto error;
2269 }
2270
2271 GETVAL(value, child, "value");
2272 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002273 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002274 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002275 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002276 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002277 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002278 goto error;
2279 }
2280
2281 if (d->mod == LY_DEVIATE_ADD) {
2282 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01002283 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002284 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2285 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002286 goto error;
2287 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002288
Radek Krejci841ec082016-04-05 13:05:17 +02002289 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02002290 if (d->flags & LYS_MAND_TRUE) {
2291 if (dev_target->nodetype == LYS_CHOICE) {
2292 if (((struct lys_node_choice *)(dev_target))->dflt) {
2293 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2294 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2295 "Adding the \"mandatory\" statement is forbidden on choice with the \"default\" statement.");
2296 goto error;
2297 }
2298 } else if (dev_target->nodetype == LYS_LEAF) {
2299 if (((struct lys_node_leaf *)(dev_target))->dflt) {
2300 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2301 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2302 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
2303 goto error;
2304 }
2305 }
Radek Krejci841ec082016-04-05 13:05:17 +02002306 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002307
Michal Vasko21be1b32016-03-07 12:31:34 +01002308 dev_target->flags |= d->flags & LYS_MAND_MASK;
2309 } else if (d->mod == LY_DEVIATE_RPL) {
2310 /* check that there was a value before */
2311 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002312 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2313 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002314 goto error;
2315 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002316
Michal Vasko21be1b32016-03-07 12:31:34 +01002317 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01002318 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01002319 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002320 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002321 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002322 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002323 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002324
2325 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2326 for (parent = dev_target->parent;
2327 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2328 parent = parent->parent) {
2329 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2330 /* stop also on presence containers */
2331 break;
2332 }
2333 }
2334 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2335 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2336 if (lyp_check_mandatory_choice(parent)) {
2337 goto error;
2338 }
2339 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002340
2341 if (read_yin_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
2342 goto error;
2343 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002344 } else if (!strcmp(child->name, "min-elements")) {
2345 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002346 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002347 goto error;
2348 }
2349 f_min = 1;
2350
Michal Vasko60f4b452016-02-12 11:02:55 +01002351 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002352 goto error;
2353 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002354 if (read_yin_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MIN, 0, unres)) {
2355 goto error;
2356 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002357 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002358 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002359 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002360 goto error;
2361 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01002362 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02002363
Michal Vasko60f4b452016-02-12 11:02:55 +01002364 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002365 goto error;
2366 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002367 if (read_yin_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MAX, 0, unres)) {
2368 goto error;
2369 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002370 } else if (!strcmp(child->name, "must")) {
2371 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002372 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002373 continue;
2374 } else if (!strcmp(child->name, "type")) {
2375 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002376 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002377 goto error;
2378 }
2379
Michal Vaskof7e57d52016-03-07 11:31:09 +01002380 /* add, del type is forbidden */
2381 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002382 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002383 goto error;
2384 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002385 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002386 goto error;
2387 }
2388
Radek Krejcieb00f512015-07-01 16:44:58 +02002389 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002390 if (dev_target->nodetype == LYS_LEAF) {
2391 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002392 if (((struct lys_node_leaf *)dev_target)->dflt) {
2393 ly_set_add(dflt_check, dev_target, 0);
2394 }
Michal Vasko60f4b452016-02-12 11:02:55 +01002395 } else if (dev_target->nodetype == LYS_LEAFLIST) {
2396 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002397 if (((struct lys_node_leaflist *)dev_target)->dflt) {
2398 ly_set_add(dflt_check, dev_target, 0);
2399 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002400 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002401 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2402 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002403 goto error;
2404 }
2405
Radek Krejcieb00f512015-07-01 16:44:58 +02002406 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002407 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01002408 /* HACK for unres */
2409 t->der = (struct lys_tpdf *)child;
Michal Vasko3767fb22016-07-21 12:10:57 +02002410 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002411 goto error;
2412 }
2413 d->type = t;
2414 } else if (!strcmp(child->name, "unique")) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002415 if (read_yin_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_UNIQUE, c_uniq, unres)) {
2416 goto error;
2417 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002418 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002419 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002420 continue;
2421 } else if (!strcmp(child->name, "units")) {
2422 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002423 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002424 goto error;
2425 }
2426
2427 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002428 if (dev_target->nodetype == LYS_LEAFLIST) {
2429 stritem = &((struct lys_node_leaflist *)dev_target)->units;
2430 } else if (dev_target->nodetype == LYS_LEAF) {
2431 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02002432 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002433 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2434 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002435 goto error;
2436 }
2437
2438 /* get units value */
2439 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002440 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02002441
2442 /* apply to target */
2443 if (d->mod == LY_DEVIATE_ADD) {
2444 /* check that there is no current value */
2445 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002446 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2447 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002448 goto error;
2449 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002450
Michal Vasko21be1b32016-03-07 12:31:34 +01002451 *stritem = lydict_insert(ctx, value, 0);
2452 } else if (d->mod == LY_DEVIATE_RPL) {
2453 /* check that there was a value before */
2454 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002455 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2456 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01002457 goto error;
2458 }
2459
2460 lydict_remove(ctx, *stritem);
2461 *stritem = lydict_insert(ctx, value, 0);
2462 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002463 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002464 if (!ly_strequal(*stritem, d->units, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002465 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2466 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002467 goto error;
2468 }
2469 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002470 lydict_remove(ctx, *stritem);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002471 (*stritem) = NULL;
2472 }
2473
2474 if (read_yin_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_UNITS, 0, unres)) {
2475 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002476 }
2477 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002478 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002479 goto error;
2480 }
2481
Michal Vasko88c29542015-11-27 14:57:53 +01002482 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002483 }
2484
2485 if (c_must) {
2486 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002487 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002488 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002489 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2490 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002491 break;
Radek Krejci76512572015-08-04 09:47:08 +02002492 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002493 trg_must = &((struct lys_node_container *)dev_target)->must;
2494 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002495 break;
Radek Krejci76512572015-08-04 09:47:08 +02002496 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002497 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2498 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002499 break;
Radek Krejci76512572015-08-04 09:47:08 +02002500 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002501 trg_must = &((struct lys_node_list *)dev_target)->must;
2502 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002503 break;
Radek Krejci76512572015-08-04 09:47:08 +02002504 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002505 case LYS_ANYDATA:
2506 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2507 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002508 break;
2509 default:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002510 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2511 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002512 goto error;
2513 }
2514
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002515 dev_target->flags &= ~LYS_XPATH_DEP;
Michal Vasko508a50d2016-09-07 14:50:33 +02002516
Radek Krejcieb00f512015-07-01 16:44:58 +02002517 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002518 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002519 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002520 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002521 } else if (d->mod == LY_DEVIATE_ADD) {
2522 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002523 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002524 if (!d->must) {
2525 LOGMEM;
2526 goto error;
2527 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002528 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02002529 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002530 d->must_size = c_must;
2531 } else { /* LY_DEVIATE_DEL */
2532 d->must = calloc(c_must, sizeof *d->must);
2533 }
Michal Vasko253035f2015-12-17 16:58:13 +01002534 if (!d->must) {
2535 LOGMEM;
2536 goto error;
2537 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002538 }
2539 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002540 /* replace unique is forbidden */
2541 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002542 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002543 goto error;
2544 }
2545
Radek Krejcieb00f512015-07-01 16:44:58 +02002546 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002547 if (dev_target->nodetype != LYS_LIST) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002548 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2549 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002550 goto error;
2551 }
2552
Michal Vasko60f4b452016-02-12 11:02:55 +01002553 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002554 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002555 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002556 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02002557 list->unique = d->unique;
2558 d->unique = &list->unique[list->unique_size];
2559 d->unique_size = c_uniq;
2560 } else { /* LY_DEVIATE_DEL */
2561 d->unique = calloc(c_uniq, sizeof *d->unique);
2562 }
Michal Vasko253035f2015-12-17 16:58:13 +01002563 if (!d->unique) {
2564 LOGMEM;
2565 goto error;
2566 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002567 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002568 if (c_dflt) {
2569 if (d->mod == LY_DEVIATE_ADD) {
2570 /* check that there is no current value */
2571 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
2572 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
2573 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2574 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
2575 goto error;
2576 }
2577
2578 /* check collision with mandatory/min-elements */
2579 if ((dev_target->flags & LYS_MAND_TRUE) ||
2580 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
2581 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2582 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2583 "Adding the \"default\" statement is forbidden on %s statement.",
2584 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2585 goto error;
2586 }
2587 } else if (d->mod == LY_DEVIATE_RPL) {
2588 /* check that there was a value before */
2589 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2590 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
2591 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2592 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
2593 goto error;
2594 }
2595 }
2596
2597 if (dev_target->nodetype == LYS_LEAFLIST) {
2598 /* reallocate default list in the target */
2599 llist = (struct lys_node_leaflist *)dev_target;
2600 if (d->mod == LY_DEVIATE_ADD) {
2601 /* reallocate (enlarge) the unique array of the target */
2602 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
2603 } else if (d->mod == LY_DEVIATE_RPL) {
2604 /* reallocate (replace) the unique array of the target */
2605 for (i = 0; i < llist->dflt_size; i++) {
2606 lydict_remove(llist->module->ctx, llist->dflt[i]);
2607 }
2608 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2609 llist->dflt_size = 0;
2610 }
2611 }
2612 d->dflt = calloc(c_dflt, sizeof *d->dflt);
2613 if (!d->dflt) {
2614 LOGMEM;
2615 goto error;
2616 }
2617 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002618 if (c_ext) {
2619 /* some extensions may be already present from the substatements */
2620 reallocated = realloc(d->ext, (c_ext + d->ext_size) * sizeof *d->ext);
2621 if (!reallocated) {
2622 LOGMEM;
2623 goto error;
2624 }
2625 d->ext = reallocated;
2626
2627 /* init memory */
2628 memset(&d->ext[d->ext_size], 0, c_ext * sizeof *d->ext);
2629 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002630
2631 /* process deviation properties with 0..n cardinality */
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002632 LY_TREE_FOR_SAFE(develem->child, next2, child) {
2633 if (strcmp(child->ns->value, LY_NSYIN)) {
2634 /* extension */
2635 if (lyp_yin_fill_ext(d, LYEXT_PAR_DEVIATE, 0, 0, module, child, &d->ext, d->ext_size, unres)) {
2636 goto error;
2637 }
2638 d->ext_size++;
2639 } else if (!strcmp(child->name, "must")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002640 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcifccd1442017-01-16 10:26:57 +01002641 if (fill_yin_must(module, child, &d->must[d->must_size], unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002642 goto error;
2643 }
2644
2645 /* find must to delete, we are ok with just matching conditions */
2646 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002647 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002648 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002649 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02002650 /* ... and maintain the array */
2651 (*trg_must_size)--;
2652 if (i != *trg_must_size) {
2653 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2654 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2655 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2656 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2657 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2658 }
2659 if (!(*trg_must_size)) {
2660 free(*trg_must);
2661 *trg_must = NULL;
2662 } else {
2663 (*trg_must)[*trg_must_size].expr = NULL;
2664 (*trg_must)[*trg_must_size].dsc = NULL;
2665 (*trg_must)[*trg_must_size].ref = NULL;
2666 (*trg_must)[*trg_must_size].eapptag = NULL;
2667 (*trg_must)[*trg_must_size].emsg = NULL;
2668 }
2669
2670 i = -1; /* set match flag */
2671 break;
2672 }
2673 }
2674 d->must_size++;
2675 if (i != -1) {
2676 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002677 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002678 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01002679 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002680 goto error;
2681 }
2682 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002683 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
Radek Krejcifccd1442017-01-16 10:26:57 +01002684 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]), unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002685 goto error;
2686 }
2687 (*trg_must_size)++;
2688 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002689
2690 /* check XPath dependencies again */
Michal Vaskoe8734262016-09-29 14:12:06 +02002691 if (*trg_must_size && unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02002692 goto error;
2693 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002694 } else if (!strcmp(child->name, "unique")) {
2695 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002696 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002697 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002698 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002699 goto error;
2700 }
2701
2702 /* find unique structures to delete */
2703 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002704 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002705 continue;
2706 }
2707
Radek Krejci581ce772015-11-10 17:22:40 +01002708 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002709 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002710 break;
2711 }
2712 }
2713
Radek Krejci581ce772015-11-10 17:22:40 +01002714 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002715 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002716 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002717 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002718 }
2719 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002720 /* ... and maintain the array */
2721 list->unique_size--;
2722 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002723 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2724 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002725 }
2726
2727 if (!list->unique_size) {
2728 free(list->unique);
2729 list->unique = NULL;
2730 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002731 list->unique[list->unique_size].expr_size = 0;
2732 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002733 }
2734
2735 i = -1; /* set match flag */
2736 break;
2737 }
2738 }
2739
2740 d->unique_size++;
2741 if (i != -1) {
2742 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002743 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2744 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002745 goto error;
2746 }
2747 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002748 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002749 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002750 list->unique_size++;
2751 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002752 goto error;
2753 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002754 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002755 } else if (!strcmp(child->name, "default")) {
2756 GETVAL(value, child, "value");
2757 u = strlen(value);
2758 d->dflt[d->dflt_size++] = lydict_insert(module->ctx, value, u);
2759
2760 if (dev_target->nodetype == LYS_CHOICE) {
2761 choice = (struct lys_node_choice *)dev_target;
2762 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2763 if (rc || !node) {
2764 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2765 goto error;
2766 }
2767 if (d->mod == LY_DEVIATE_DEL) {
2768 if (!choice->dflt || (choice->dflt != node)) {
2769 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2770 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2771 goto error;
2772 }
2773 } else { /* add or replace */
2774 choice->dflt = node;
2775 if (!choice->dflt) {
2776 /* default branch not found */
2777 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2778 goto error;
2779 }
2780 }
2781 } else if (dev_target->nodetype == LYS_LEAF) {
2782 leaf = (struct lys_node_leaf *)dev_target;
2783 if (d->mod == LY_DEVIATE_DEL) {
2784 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
2785 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2786 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2787 goto error;
2788 }
2789 /* remove value */
2790 lydict_remove(ctx, leaf->dflt);
2791 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01002792 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002793 } else { /* add (already checked) and replace */
2794 /* remove value */
2795 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01002796 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002797
2798 /* set new value */
2799 leaf->dflt = lydict_insert(ctx, value, u);
2800
Radek Krejcibd117f02016-11-04 16:28:08 +01002801 /* remember to check it later (it may not fit now, because the type can be deviated too) */
Radek Krejcid5a5c282016-08-15 15:38:08 +02002802 ly_set_add(dflt_check, dev_target, 0);
2803 }
2804 } else { /* LYS_LEAFLIST */
2805 llist = (struct lys_node_leaflist *)dev_target;
2806 if (d->mod == LY_DEVIATE_DEL) {
2807 /* find and remove the value in target list */
2808 for (i = 0; i < llist->dflt_size; i++) {
2809 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
2810 /* match, remove the value */
2811 lydict_remove(llist->module->ctx, llist->dflt[i]);
2812 llist->dflt[i] = NULL;
2813 break;
2814 }
2815 }
2816 if (i == llist->dflt_size) {
2817 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2818 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
2819 goto error;
2820 }
2821 } else {
2822 /* add or replace, anyway we place items into the deviate's list
2823 which propagates to the target */
2824 /* we just want to check that the value isn't already in the list */
2825 for (i = 0; i < llist->dflt_size; i++) {
2826 if (ly_strequal(llist->dflt[i], value, 1)) {
2827 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2828 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2829 goto error;
2830 }
2831 }
2832 /* store it in target node */
2833 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, u);
2834
2835 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2836 ly_set_add(dflt_check, dev_target, 0);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002837 llist->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002838 }
2839 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002840 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002841 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002842
2843 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
2844 /* consolidate the final list in the target after removing items from it */
2845 llist = (struct lys_node_leaflist *)dev_target;
2846 for (i = j = 0; j < llist->dflt_size; j++) {
2847 llist->dflt[i] = llist->dflt[j];
2848 if (llist->dflt[i]) {
2849 i++;
2850 }
2851 }
2852 llist->dflt_size = i + 1;
2853 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002854 }
2855
Michal Vasko43a1feb2016-03-07 12:03:02 +01002856 /* now check whether default value, if any, matches the type */
Pavol Vican85991ec2016-08-16 14:58:12 +02002857 for (u = 0; u < dflt_check->number; ++u) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002858 value = NULL;
2859 rc = EXIT_SUCCESS;
2860 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2861 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
Radek Krejci51673202016-11-01 17:00:32 +01002862 value = leaf->dflt;
2863 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002864 } else { /* LYS_LEAFLIST */
2865 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2866 for (j = 0; j < llist->dflt_size; j++) {
Radek Krejci51673202016-11-01 17:00:32 +01002867 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2868 (struct lys_node *)(&llist->dflt[j]));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002869 if (rc == -1) {
Radek Krejci51673202016-11-01 17:00:32 +01002870 value = llist->dflt[j];
Radek Krejcid5a5c282016-08-15 15:38:08 +02002871 break;
2872 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002873 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002874
2875 }
2876 if (rc == -1) {
2877 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2878 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2879 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2880 dev->target_name);
2881 goto error;
Michal Vasko43a1feb2016-03-07 12:03:02 +01002882 }
2883 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002884
Radek Krejci27fe55e2016-09-13 17:13:35 +02002885 /* mark all the affected modules as deviated and implemented */
2886 for(parent = dev_target; parent; parent = lys_parent(parent)) {
2887 mod = lys_node_module(parent);
2888 if (module != mod) {
2889 mod->deviated = 1;
2890 lys_set_implemented(mod);
2891 }
2892 }
2893
Radek Krejcid5a5c282016-08-15 15:38:08 +02002894 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002895 return EXIT_SUCCESS;
2896
2897error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002898 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002899 return EXIT_FAILURE;
2900}
2901
Michal Vasko0d343d12015-08-24 14:57:36 +02002902/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002903static int
Radek Krejcib8048692015-08-05 13:36:34 +02002904fill_yin_augment(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_node_augment *aug,
Michal Vaskof02e3742015-08-05 16:27:02 +02002905 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02002906{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002907 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01002908 struct lyxml_elem *sub, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002909 struct lys_node *node;
Radek Krejcie534c132016-11-23 13:32:31 +01002910 int ret, c_ftrs = 0, c_ext = 0;
Radek Krejci30701b42017-01-23 16:41:38 +01002911 void *reallocated;
Radek Krejci106efc02015-06-10 14:36:27 +02002912
Michal Vasko591e0b22015-08-13 13:53:43 +02002913 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002914 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002915 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02002916 if (!aug->target_name) {
2917 goto error;
2918 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002919 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02002920
Radek Krejci07d0fb92017-01-13 14:11:05 +01002921 if (read_yin_common(module, NULL, aug, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002922 goto error;
2923 }
2924
Radek Krejcie534c132016-11-23 13:32:31 +01002925 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2926 if (strcmp(sub->ns->value, LY_NSYIN)) {
2927 /* extension */
2928 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02002929 continue;
Radek Krejci30701b42017-01-23 16:41:38 +01002930 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejcie534c132016-11-23 13:32:31 +01002931 c_ftrs++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002932 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01002933 } else if (!strcmp(sub->name, "when")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002934 if (aug->when) {
Radek Krejcie534c132016-11-23 13:32:31 +01002935 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002936 goto error;
2937 }
2938
Radek Krejci5323b492017-01-16 15:40:11 +01002939 aug->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002940 if (!aug->when) {
Radek Krejcie534c132016-11-23 13:32:31 +01002941 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002942 goto error;
2943 }
Radek Krejcie534c132016-11-23 13:32:31 +01002944 lyxml_free(module->ctx, sub);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002945 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002946
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002947 /* check allowed data sub-statements */
Radek Krejcie534c132016-11-23 13:32:31 +01002948 } else if (!strcmp(sub->name, "container")) {
2949 node = read_yin_container(module, (struct lys_node *)aug, sub, 1, unres);
2950 } else if (!strcmp(sub->name, "leaf-list")) {
2951 node = read_yin_leaflist(module, (struct lys_node *)aug, sub, 1, unres);
2952 } else if (!strcmp(sub->name, "leaf")) {
2953 node = read_yin_leaf(module, (struct lys_node *)aug, sub, 1, unres);
2954 } else if (!strcmp(sub->name, "list")) {
2955 node = read_yin_list(module, (struct lys_node *)aug, sub, 1, unres);
2956 } else if (!strcmp(sub->name, "uses")) {
2957 node = read_yin_uses(module, (struct lys_node *)aug, sub, unres);
2958 } else if (!strcmp(sub->name, "choice")) {
2959 node = read_yin_choice(module, (struct lys_node *)aug, sub, 1, unres);
2960 } else if (!strcmp(sub->name, "case")) {
2961 node = read_yin_case(module, (struct lys_node *)aug, sub, 1, unres);
2962 } else if (!strcmp(sub->name, "anyxml")) {
2963 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYXML, 1, unres);
2964 } else if (!strcmp(sub->name, "anydata")) {
2965 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYDATA, 1, unres);
2966 } else if (!strcmp(sub->name, "action")) {
2967 node = read_yin_rpc_action(module, (struct lys_node *)aug, sub, unres);
2968 } else if (!strcmp(sub->name, "notification")) {
2969 node = read_yin_notif(module, (struct lys_node *)aug, sub, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002970 } else {
Radek Krejcie534c132016-11-23 13:32:31 +01002971 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002972 goto error;
2973 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002974
Radek Krejci1d82ef62015-08-07 14:44:40 +02002975 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002976 goto error;
2977 }
2978
Radek Krejci1d82ef62015-08-07 14:44:40 +02002979 node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01002980 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002981 }
2982
Radek Krejcie534c132016-11-23 13:32:31 +01002983 if (c_ftrs) {
2984 aug->iffeature = calloc(c_ftrs, sizeof *aug->iffeature);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002985 if (!aug->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002986 LOGMEM;
2987 goto error;
2988 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002989 }
Radek Krejcie534c132016-11-23 13:32:31 +01002990 if (c_ext) {
Radek Krejci30701b42017-01-23 16:41:38 +01002991 /* some extensions may be already present from the substatements */
2992 reallocated = realloc(aug->ext, (c_ext + aug->ext_size) * sizeof *aug->ext);
2993 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01002994 LOGMEM;
2995 goto error;
2996 }
Radek Krejci30701b42017-01-23 16:41:38 +01002997 aug->ext = reallocated;
2998
2999 /* init memory */
3000 memset(&aug->ext[aug->ext_size], 0, c_ext * sizeof *aug->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003001 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003002
Radek Krejcie534c132016-11-23 13:32:31 +01003003 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3004 if (strcmp(sub->ns->value, LY_NSYIN)) {
3005 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003006 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 +01003007 aug->ext_size++;
3008 if (ret) {
3009 goto error;
3010 }
3011 } else if (!strcmp(sub->name, "if-feature")) {
3012 ret = fill_yin_iffeature((struct lys_node *)aug, 0, sub, &aug->iffeature[aug->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003013 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003014 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003015 goto error;
3016 }
Radek Krejcie534c132016-11-23 13:32:31 +01003017 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003018 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003019 }
3020
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003021 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02003022 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02003023 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02003024 * when the uses does and cannot be resolved now for sure
3025 * (the grouping was not yet copied into uses).
3026 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02003027 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003028 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02003029 goto error;
3030 }
Michal Vasko49291b32015-08-06 09:49:41 +02003031 }
Radek Krejci106efc02015-06-10 14:36:27 +02003032
Michal Vasko508a50d2016-09-07 14:50:33 +02003033 /* check XPath dependencies */
3034 if (aug->when && (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1)) {
3035 goto error;
3036 }
3037
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003038 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02003039
3040error:
3041
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003042 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02003043}
3044
Michal Vasko0d343d12015-08-24 14:57:36 +02003045/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003046static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02003047fill_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 +02003048{
Radek Krejci363bd4a2016-07-29 14:30:20 +02003049 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003050 struct lyxml_elem *sub, *next;
3051 const char *value;
3052 char *endptr;
3053 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01003054 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003055 int r;
3056 unsigned long int val;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003057 void *reallocated;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003058
Radek Krejci363bd4a2016-07-29 14:30:20 +02003059 assert(uses);
3060 module = uses->module; /* shorthand */
3061
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003062 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003063 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02003064 if (!rfn->target_name) {
3065 goto error;
3066 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003067
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003068 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003069 if (!sub->ns) {
3070 /* garbage */
3071 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01003072 /* extension */
3073 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003074 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02003075
Radek Krejci411b1bf2017-01-23 16:40:05 +01003076 } else if (!strcmp(sub->name, "description")) {
3077 if (rfn->dsc) {
3078 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3079 goto error;
3080 }
3081
3082 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
3083 goto error;
3084 }
3085
3086 rfn->dsc = read_yin_subnode(module->ctx, sub, "text");
3087 if (!rfn->dsc) {
3088 goto error;
3089 }
3090 } else if (!strcmp(sub->name, "reference")) {
3091 if (rfn->ref) {
3092 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3093 goto error;
3094 }
3095
3096 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
3097 goto error;
3098 }
3099
3100 rfn->ref = read_yin_subnode(module->ctx, sub, "text");
3101 if (!rfn->ref) {
3102 goto error;
3103 }
3104 } else if (!strcmp(sub->name, "config")) {
3105 if (rfn->flags & LYS_CONFIG_MASK) {
3106 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3107 goto error;
3108 }
3109 GETVAL(value, sub, "value");
3110 if (!strcmp(value, "false")) {
3111 rfn->flags |= LYS_CONFIG_R;
3112 } else if (!strcmp(value, "true")) {
3113 rfn->flags |= LYS_CONFIG_W;
3114 } else {
3115 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3116 goto error;
3117 }
3118 rfn->flags |= LYS_CONFIG_SET;
3119
3120 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
3121 goto error;
3122 }
Radek Krejcie534c132016-11-23 13:32:31 +01003123 } else if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02003124 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02003125
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003126 /* check possibility of statements combination */
3127 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02003128 if (c_dflt) {
3129 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003130 if (module->version < 2) {
3131 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3132 goto error;
3133 }
Radek Krejci200bf712016-08-16 17:11:04 +02003134 rfn->target_type &= LYS_LEAFLIST;
3135 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003136 if (module->version < 2) {
3137 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
3138 } else {
3139 /* YANG 1.1 */
3140 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
3141 }
Radek Krejci200bf712016-08-16 17:11:04 +02003142 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003143 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003144 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3145 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003146 goto error;
3147 }
3148 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003149 if (module->version < 2) {
3150 rfn->target_type = LYS_LEAF | LYS_CHOICE;
3151 } else {
3152 /* YANG 1.1 */
3153 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
3154 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003155 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003156
Radek Krejcifdc0d702017-01-23 15:58:38 +01003157 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DEFAULT, c_dflt, unres)) {
3158 goto error;
3159 }
Radek Krejci200bf712016-08-16 17:11:04 +02003160 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003161 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003162 } else if (!strcmp(sub->name, "mandatory")) {
3163 /* leaf, choice or anyxml */
3164 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003165 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003166 goto error;
3167 }
3168 /* just checking the flags in leaf is not sufficient, we would allow
3169 * multiple mandatory statements with the "false" value
3170 */
3171 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003172
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003173 /* check possibility of statements combination */
3174 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003175 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003176 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003177 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3178 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003179 goto error;
3180 }
3181 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003182 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003183 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003184
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003185 GETVAL(value, sub, "value");
3186 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003187 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003188 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003189 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003190 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003191 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003192 goto error;
3193 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01003194 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
3195 goto error;
3196 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003197 } else if (!strcmp(sub->name, "min-elements")) {
3198 /* list or leaf-list */
3199 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003200 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003201 goto error;
3202 }
3203 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003204
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003205 /* check possibility of statements combination */
3206 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003207 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003208 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003209 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3210 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003211 goto error;
3212 }
3213 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003214 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003215 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003216
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003217 GETVAL(value, sub, "value");
3218 while (isspace(value[0])) {
3219 value++;
3220 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003221
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003222 /* convert it to uint32_t */
3223 errno = 0;
3224 endptr = NULL;
3225 val = strtoul(value, &endptr, 10);
3226 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003227 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003228 goto error;
3229 }
3230 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003231 rfn->flags |= LYS_RFN_MINSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003232
3233 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
3234 goto error;
3235 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003236 } else if (!strcmp(sub->name, "max-elements")) {
3237 /* list or leaf-list */
3238 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003239 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003240 goto error;
3241 }
3242 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003243
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003244 /* check possibility of statements combination */
3245 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003246 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003247 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003248 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3249 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003250 goto error;
3251 }
3252 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003253 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003254 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003255
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003256 GETVAL(value, sub, "value");
3257 while (isspace(value[0])) {
3258 value++;
3259 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003260
Radek Krejci0d7b2472016-02-12 11:11:03 +01003261 if (!strcmp(value, "unbounded")) {
3262 rfn->mod.list.max = 0;
3263 } else {
3264 /* convert it to uint32_t */
3265 errno = 0;
3266 endptr = NULL;
3267 val = strtoul(value, &endptr, 10);
3268 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003269 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003270 goto error;
3271 }
3272 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003273 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003274 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003275
3276 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
3277 goto error;
3278 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003279 } else if (!strcmp(sub->name, "presence")) {
3280 /* container */
3281 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003282 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003283 goto error;
3284 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003286 /* check possibility of statements combination */
3287 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003288 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003289 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003290 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3291 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003292 goto error;
3293 }
3294 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003295 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003296 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003298 GETVAL(value, sub, "value");
3299 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcifdc0d702017-01-23 15:58:38 +01003300
3301 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
3302 goto error;
3303 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003304 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02003305 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003306 /* check possibility of statements combination */
3307 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003308 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003309 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003310 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3311 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003312 goto error;
3313 }
3314 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003315 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003316 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003317
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003318 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003319 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003320
Radek Krejci363bd4a2016-07-29 14:30:20 +02003321 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
3322 /* leaf, leaf-list, list, container or anyxml */
3323 /* check possibility of statements combination */
3324 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003325 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003326 if (!rfn->target_type) {
3327 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3328 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
3329 goto error;
3330 }
3331 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003332 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003333 }
3334
3335 c_ftrs++;
3336 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003337 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003338 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003339 goto error;
3340 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003341
Michal Vasko345da0a2015-12-02 10:35:55 +01003342 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003343 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003344
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003345 /* process nodes with cardinality of 0..n */
3346 if (c_must) {
3347 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003348 if (!rfn->must) {
3349 LOGMEM;
3350 goto error;
3351 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003352 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02003353 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02003354 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003355 if (!rfn->iffeature) {
3356 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02003357 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003358 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003359 }
Radek Krejci200bf712016-08-16 17:11:04 +02003360 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003361 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Radek Krejci200bf712016-08-16 17:11:04 +02003362 if (!rfn->dflt) {
3363 LOGMEM;
3364 goto error;
3365 }
3366 }
Radek Krejcie534c132016-11-23 13:32:31 +01003367 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003368 /* some extensions may be already present from the substatements */
3369 reallocated = realloc(rfn->ext, (c_ext + rfn->ext_size) * sizeof *rfn->ext);
3370 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003371 LOGMEM;
3372 goto error;
3373 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01003374 rfn->ext = reallocated;
3375
3376 /* init memory */
3377 memset(&rfn->ext[rfn->ext_size], 0, c_ext * sizeof *rfn->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003378 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003379
Radek Krejcie534c132016-11-23 13:32:31 +01003380 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3381 if (strcmp(sub->ns->value, LY_NSYIN)) {
3382 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003383 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 +01003384 rfn->ext_size++;
3385 if (r) {
3386 goto error;
3387 }
3388 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003389 r = fill_yin_iffeature(uses, 0, sub, &rfn->iffeature[rfn->iffeature_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003390 rfn->iffeature_size++;
3391 if (r) {
3392 goto error;
3393 }
Radek Krejci200bf712016-08-16 17:11:04 +02003394 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01003395 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003396 rfn->must_size++;
3397 if (r) {
3398 goto error;
3399 }
Radek Krejci200bf712016-08-16 17:11:04 +02003400 } else { /* default */
3401 GETVAL(value, sub, "value");
3402
3403 /* check for duplicity */
3404 for (r = 0; r < rfn->dflt_size; r++) {
3405 if (ly_strequal(rfn->dflt[r], value, 1)) {
3406 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3407 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
3408 goto error;
3409 }
3410 }
3411 rfn->dflt[rfn->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02003412 }
3413 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003414
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003415 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003416
3417error:
3418
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003419 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003420}
3421
Michal Vasko0d343d12015-08-24 14:57:36 +02003422/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003423static int
Radek Krejcie534c132016-11-23 13:32:31 +01003424fill_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 +02003425{
Radek Krejcie534c132016-11-23 13:32:31 +01003426 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003427 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003428 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003429 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003430
Radek Krejcie534c132016-11-23 13:32:31 +01003431 /* init */
3432 memset(&exts, 0, sizeof exts);
3433
3434 LY_TREE_FOR_SAFE(yin->child, next, child) {
3435 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003436 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003437 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003438 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3439 /* extension */
3440 c_ext++;
3441 lyxml_unlink_elem(module->ctx, child, 2);
3442 lyxml_add_child(module->ctx, &exts, child);
3443 } else if (!strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003444 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01003445 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003446 goto error;
3447 }
3448 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01003449
3450 if (read_yin_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
3451 goto error;
3452 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003453 } else if (!strcmp(child->name, "revision-date")) {
3454 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02003455 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3456 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003457 }
3458 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003459 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003460 goto error;
3461 }
3462 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003463
3464 if (read_yin_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
3465 goto error;
3466 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003467 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003468 if (imp->dsc) {
3469 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3470 goto error;
3471 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003472 if (read_yin_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
3473 goto error;
3474 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003475 imp->dsc = read_yin_subnode(module->ctx, child, "text");
3476 if (!imp->dsc) {
3477 goto error;
3478 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003479 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003480 if (imp->ref) {
3481 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3482 goto error;
3483 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003484 if (read_yin_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
3485 goto error;
3486 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003487 imp->ref = read_yin_subnode(module->ctx, child, "text");
3488 if (!imp->ref) {
3489 goto error;
3490 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003491 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003492 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003493 goto error;
3494 }
3495 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003496
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003497 /* check mandatory information */
3498 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003499 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003500 goto error;
3501 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003502
Radek Krejcie534c132016-11-23 13:32:31 +01003503 /* process extensions */
3504 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003505 /* some extensions may be already present from the substatements */
3506 reallocated = realloc(imp->ext, (c_ext + imp->ext_size) * sizeof *imp->ext);
3507 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003508 LOGMEM;
3509 goto error;
3510 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003511 imp->ext = reallocated;
3512
3513 /* init memory */
3514 memset(&imp->ext[imp->ext_size], 0, c_ext * sizeof *imp->ext);
3515
Radek Krejcie534c132016-11-23 13:32:31 +01003516 LY_TREE_FOR_SAFE(exts.child, next, child) {
3517 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003518 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 +01003519 imp->ext_size++;
3520 if (r) {
3521 goto error;
3522 }
3523 }
3524 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003525
Radek Krejcie534c132016-11-23 13:32:31 +01003526 GETVAL(value, yin, "module");
Pavol Vicane994fda2016-03-22 10:47:58 +01003527 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02003528
3529error:
3530
Radek Krejcie534c132016-11-23 13:32:31 +01003531 while (exts.child) {
3532 lyxml_free(module->ctx, exts.child);
3533 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003534 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02003535}
3536
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003537/* logs directly
3538 * returns:
3539 * 0 - inc successfully filled
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003540 * -1 - error
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003541 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003542static int
Michal Vasko5ff78822016-02-12 09:33:31 +01003543fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
3544 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02003545{
Radek Krejcie534c132016-11-23 13:32:31 +01003546 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003547 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003548 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003549 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003550
Radek Krejcie534c132016-11-23 13:32:31 +01003551 /* init */
3552 memset(&exts, 0, sizeof exts);
3553
3554 LY_TREE_FOR_SAFE(yin->child, next, child) {
3555 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003556 /* garbage */
3557 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003558 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3559 /* extension */
3560 c_ext++;
3561 lyxml_unlink_elem(module->ctx, child, 2);
3562 lyxml_add_child(module->ctx, &exts, child);
3563 } else if (!strcmp(child->name, "revision-date")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003564 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003565 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003566 goto error;
3567 }
3568 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003569 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003570 goto error;
3571 }
3572 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003573
3574 if (read_yin_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
3575 goto error;
3576 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003577 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003578 if (inc->dsc) {
3579 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3580 goto error;
3581 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003582 if (read_yin_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
3583 goto error;
3584 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003585 inc->dsc = read_yin_subnode(module->ctx, child, "text");
3586 if (!inc->dsc) {
3587 goto error;
3588 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003589 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003590 if (inc->ref) {
3591 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3592 goto error;
3593 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003594 if (read_yin_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
3595 goto error;
3596 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003597 inc->ref = read_yin_subnode(module->ctx, child, "text");
3598 if (!inc->ref) {
3599 goto error;
3600 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003601 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003602 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003603 goto error;
3604 }
3605 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003606
Radek Krejcie534c132016-11-23 13:32:31 +01003607 /* process extensions */
3608 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003609 /* some extensions may be already present from the substatements */
3610 reallocated = realloc(inc->ext, (c_ext + inc->ext_size) * sizeof *inc->ext);
3611 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003612 LOGMEM;
3613 goto error;
3614 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003615 inc->ext = reallocated;
3616
3617 /* init memory */
3618 memset(&inc->ext[inc->ext_size], 0, c_ext * sizeof *inc->ext);
3619
Radek Krejcie534c132016-11-23 13:32:31 +01003620 LY_TREE_FOR_SAFE(exts.child, next, child) {
3621 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003622 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 +01003623 inc->ext_size++;
3624 if (r) {
3625 goto error;
3626 }
3627 }
3628 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003629
Radek Krejcie534c132016-11-23 13:32:31 +01003630 GETVAL(value, yin, "module");
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003631 return lyp_check_include(submodule ? (struct lys_module *)submodule : module, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02003632
3633error:
3634
Radek Krejci83e3f5b2016-06-24 14:55:25 +02003635 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02003636}
3637
Michal Vasko0d343d12015-08-24 14:57:36 +02003638/* logs directly
3639 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003640 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02003641 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02003642 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003643 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003644static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01003645read_yin_common(struct lys_module *module, struct lys_node *parent, void *stmt, LYEXT_PAR stmt_type,
3646 struct lyxml_elem *xmlnode, int opt, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003647{
Radek Krejci07d0fb92017-01-13 14:11:05 +01003648 struct lys_node *node = stmt;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003649 const char *value;
3650 struct lyxml_elem *sub, *next;
3651 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003652
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003653 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003654 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003655 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003657 if (opt & OPT_IDENT) {
3658 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01003659 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003660 goto error;
3661 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003662 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003663 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003664
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003665 /* process local parameters */
3666 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003667 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003668 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003669 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02003670 continue;
3671 }
3672 if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejci6ff885d2017-01-03 14:06:22 +01003673 /* possibly an extension, keep the node for later processing, so skipping lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003674 continue;
3675 }
3676
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003677 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003678 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003679 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003680 goto error;
3681 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003682
Radek Krejciac00b2a2017-01-17 14:05:00 +01003683 if (read_yin_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003684 goto error;
3685 }
3686
Radek Krejci1d82ef62015-08-07 14:44:40 +02003687 node->dsc = read_yin_subnode(ctx, sub, "text");
3688 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003689 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003690 }
3691 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003692 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003693 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003694 goto error;
3695 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003696
Radek Krejciac00b2a2017-01-17 14:05:00 +01003697 if (read_yin_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003698 goto error;
3699 }
3700
Radek Krejci1d82ef62015-08-07 14:44:40 +02003701 node->ref = read_yin_subnode(ctx, sub, "text");
3702 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003703 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003704 }
3705 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003706 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003707 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003708 goto error;
3709 }
3710 GETVAL(value, sub, "value");
3711 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003712 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003713 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003714 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003715 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003716 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003717 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003718 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003719 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003720 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003721
Radek Krejciac00b2a2017-01-17 14:05:00 +01003722 if (read_yin_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_STATUS, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003723 goto error;
3724 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003725 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3726 if (opt & OPT_CFG_PARSE) {
3727 if (node->flags & LYS_CONFIG_MASK) {
3728 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
3729 goto error;
3730 }
3731 GETVAL(value, sub, "value");
3732 if (!strcmp(value, "false")) {
3733 node->flags |= LYS_CONFIG_R;
3734 } else if (!strcmp(value, "true")) {
3735 node->flags |= LYS_CONFIG_W;
3736 } else {
3737 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3738 goto error;
3739 }
3740 node->flags |= LYS_CONFIG_SET;
Radek Krejci07d0fb92017-01-13 14:11:05 +01003741
Radek Krejciac00b2a2017-01-17 14:05:00 +01003742 if (read_yin_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003743 goto error;
3744 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003745 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003746 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003747 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003748 continue;
3749 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003750 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003751 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003752
Michal Vaskoe022a562016-09-27 14:24:15 +02003753 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003754 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02003755 if (parent) {
3756 node->flags |= parent->flags & LYS_CONFIG_MASK;
3757 } else if (!parent) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003758 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003759 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003760 }
3761 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003762
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003763 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02003764
3765error:
3766
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003767 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003768}
3769
Michal Vasko0d343d12015-08-24 14:57:36 +02003770/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003771static struct lys_when *
Radek Krejci5323b492017-01-16 15:40:11 +01003772read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003773{
Radek Krejci76512572015-08-04 09:47:08 +02003774 struct lys_when *retval = NULL;
Radek Krejci5323b492017-01-16 15:40:11 +01003775 struct lyxml_elem *child, *next;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003776 const char *value;
3777
3778 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01003779 if (!retval) {
3780 LOGMEM;
3781 return NULL;
3782 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003783
3784 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01003785 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02003786 if (!retval->cond) {
3787 goto error;
3788 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003789
Radek Krejci5323b492017-01-16 15:40:11 +01003790 LY_TREE_FOR_SAFE(yin->child, next, child) {
3791 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003792 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003793 continue;
Radek Krejci5323b492017-01-16 15:40:11 +01003794 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3795 /* extensions */
Radek Krejciac00b2a2017-01-17 14:05:00 +01003796 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003797 goto error;
3798 }
3799 } else if (!strcmp(child->name, "description")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003800 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003801 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003802 goto error;
3803 }
Radek Krejci5323b492017-01-16 15:40:11 +01003804
Radek Krejciac00b2a2017-01-17 14:05:00 +01003805 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003806 goto error;
3807 }
3808
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003809 retval->dsc = read_yin_subnode(module->ctx, child, "text");
3810 if (!retval->dsc) {
3811 goto error;
3812 }
3813 } else if (!strcmp(child->name, "reference")) {
3814 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003815 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003816 goto error;
3817 }
Radek Krejci5323b492017-01-16 15:40:11 +01003818
Radek Krejciac00b2a2017-01-17 14:05:00 +01003819 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003820 goto error;
3821 }
3822
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003823 retval->ref = read_yin_subnode(module->ctx, child, "text");
3824 if (!retval->ref) {
3825 goto error;
3826 }
3827 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003828 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003829 goto error;
3830 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003831 }
3832
3833 return retval;
3834
3835error:
3836
Michal Vasko0308dd62015-10-07 09:14:40 +02003837 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003838 return NULL;
3839}
3840
Michal Vasko0d343d12015-08-24 14:57:36 +02003841/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003842static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003843read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02003844 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02003845{
Michal Vasko29fc0182015-08-24 15:02:39 +02003846 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003847 struct lys_node_case *cs;
3848 struct lys_node *retval, *node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01003849 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01003850 void *reallocated;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003851
Radek Krejcie867c852015-08-27 09:52:34 +02003852 /* init */
3853 memset(&root, 0, sizeof root);
3854
Radek Krejci1d82ef62015-08-07 14:44:40 +02003855 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01003856 if (!cs) {
3857 LOGMEM;
3858 return NULL;
3859 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003860 cs->nodetype = LYS_CASE;
3861 cs->prev = (struct lys_node *)cs;
3862 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003863
Radek Krejci07d0fb92017-01-13 14:11:05 +01003864 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
3865 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_INHERIT : 0), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003866 goto error;
3867 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003868
Radek Krejcia9544502015-08-14 08:24:29 +02003869 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3870
Michal Vasko3a0043f2015-08-12 12:11:30 +02003871 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003872 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003873 goto error;
3874 }
3875
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003876 /* process choice's specific children */
3877 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01003878 if (strcmp(sub->ns->value, LY_NSYIN)) {
3879 /* extension */
3880 c_ext++;
3881 } else if (!strcmp(sub->name, "container") ||
Michal Vasko29fc0182015-08-24 15:02:39 +02003882 !strcmp(sub->name, "leaf-list") ||
3883 !strcmp(sub->name, "leaf") ||
3884 !strcmp(sub->name, "list") ||
3885 !strcmp(sub->name, "uses") ||
3886 !strcmp(sub->name, "choice") ||
3887 !strcmp(sub->name, "anyxml")) {
3888
Michal Vaskof3930de2015-10-22 12:03:59 +02003889 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02003890 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003891 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02003892 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003893 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003894 if (cs->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003895 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003896 goto error;
3897 }
3898
Radek Krejci5323b492017-01-16 15:40:11 +01003899 cs->when = read_yin_when(module, sub, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02003900 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003901 goto error;
3902 }
Michal Vasko29fc0182015-08-24 15:02:39 +02003903
Michal Vasko345da0a2015-12-02 10:35:55 +01003904 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003905 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003906 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003907 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003908 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003909 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003910
Radek Krejci3cf9e222015-06-18 11:37:50 +02003911 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003912 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
3913 if (!cs->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003914 LOGMEM;
3915 goto error;
3916 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003917 }
Radek Krejcie534c132016-11-23 13:32:31 +01003918 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01003919 /* some extensions may be already present from the substatements */
3920 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
3921 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003922 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003923 goto error;
3924 }
Radek Krejci21c81652017-01-23 10:42:55 +01003925 retval->ext = reallocated;
3926
3927 /* init memory */
3928 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003929 }
Radek Krejci21c81652017-01-23 10:42:55 +01003930
Radek Krejcie534c132016-11-23 13:32:31 +01003931 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3932 if (strcmp(sub->ns->value, LY_NSYIN)) {
3933 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003934 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 +01003935 retval->ext_size++;
3936 if (ret) {
3937 goto error;
3938 }
3939 } else {
3940 /* if-feature */
3941 ret = fill_yin_iffeature(retval, 0, sub, &cs->iffeature[cs->iffeature_size], unres);
3942 cs->iffeature_size++;
3943 if (ret) {
3944 goto error;
3945 }
3946 }
3947 }
Radek Krejcib388c152015-06-04 17:03:03 +02003948
Michal Vasko29fc0182015-08-24 15:02:39 +02003949 /* last part - process data nodes */
3950 LY_TREE_FOR_SAFE(root.child, next, sub) {
3951 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003952 node = read_yin_container(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003953 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003954 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003955 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003956 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003957 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003958 node = read_yin_list(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003959 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003960 node = read_yin_choice(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003961 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003962 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003963 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003964 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02003965 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003966 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003967 }
3968 if (!node) {
3969 goto error;
3970 }
3971
Michal Vasko345da0a2015-12-02 10:35:55 +01003972 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02003973 }
3974
Michal Vasko508a50d2016-09-07 14:50:33 +02003975 /* check XPath dependencies */
3976 if (cs->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3977 goto error;
3978 }
3979
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003980 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003981
3982error:
3983
Michal Vasko29fc0182015-08-24 15:02:39 +02003984 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003985 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02003986 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003987 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02003988
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003989 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003990}
3991
Michal Vasko0d343d12015-08-24 14:57:36 +02003992/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003993static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003994read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
3995 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003996{
Radek Krejci629cdef2016-06-06 15:06:36 +02003997 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003998 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003999 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02004000 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02004001 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01004002 int f_mand = 0, c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004003 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004004
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004005 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01004006 if (!choice) {
4007 LOGMEM;
4008 return NULL;
4009 }
Radek Krejci76512572015-08-04 09:47:08 +02004010 choice->nodetype = LYS_CHOICE;
4011 choice->prev = (struct lys_node *)choice;
4012 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004013
Radek Krejci07d0fb92017-01-13 14:11:05 +01004014 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4015 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004016 goto error;
4017 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004018
Radek Krejcia9544502015-08-14 08:24:29 +02004019 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4020
Michal Vasko3a0043f2015-08-12 12:11:30 +02004021 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004022 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004023 goto error;
4024 }
4025
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004026 /* process choice's specific children */
4027 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004028 if (strcmp(sub->ns->value, LY_NSYIN)) {
4029 /* extension */
4030 c_ext++;
4031 /* keep it for later processing, skip lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02004032 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004033 } else if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004034 if (!(node = read_yin_container(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004035 goto error;
4036 }
4037 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004038 if (!(node = read_yin_leaflist(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004039 goto error;
4040 }
4041 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004042 if (!(node = read_yin_leaf(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004043 goto error;
4044 }
4045 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004046 if (!(node = read_yin_list(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004047 goto error;
4048 }
4049 } else if (!strcmp(sub->name, "case")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004050 if (!(node = read_yin_case(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004051 goto error;
4052 }
4053 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004054 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004055 goto error;
4056 }
4057 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004058 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004059 goto error;
4060 }
4061 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02004062 if (dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004063 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004064 goto error;
4065 }
Radek Krejci21c81652017-01-23 10:42:55 +01004066
4067 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
4068 goto error;
4069 }
4070
Radek Krejci629cdef2016-06-06 15:06:36 +02004071 dflt = sub;
4072 lyxml_unlink_elem(ctx, dflt, 0);
Radek Krejcif9a312c2016-06-06 15:14:30 +02004073 continue;
4074 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
4075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004076 } else if (!strcmp(sub->name, "mandatory")) {
4077 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004078 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004079 goto error;
4080 }
4081 /* just checking the flags in leaf is not sufficient, we would allow
4082 * multiple mandatory statements with the "false" value
4083 */
4084 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004086 GETVAL(value, sub, "value");
4087 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004088 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004089 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004090 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004091 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004092 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004093 goto error;
4094 } /* else false is the default value, so we can ignore it */
Radek Krejci21c81652017-01-23 10:42:55 +01004095
4096 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
4097 goto error;
4098 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004099 } else if (!strcmp(sub->name, "when")) {
4100 if (choice->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004101 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004102 goto error;
4103 }
4104
Radek Krejci5323b492017-01-16 15:40:11 +01004105 choice->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004106 if (!choice->when) {
4107 goto error;
4108 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004109 } else if (!strcmp(sub->name, "if-feature")) {
4110 c_ftrs++;
4111
Michal Vasko345da0a2015-12-02 10:35:55 +01004112 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02004113 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02004114 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004115 if (!(node = read_yin_choice(module, retval, sub, valid_config, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02004116 goto error;
4117 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004118 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004119 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004120 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004121 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004122
Radek Krejci1d82ef62015-08-07 14:44:40 +02004123 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01004124 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004125 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004126
Radek Krejci3cf9e222015-06-18 11:37:50 +02004127 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004128 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
4129 if (!choice->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004130 LOGMEM;
4131 goto error;
4132 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004133 }
Radek Krejcie534c132016-11-23 13:32:31 +01004134 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004135 /* some extensions may be already present from the substatements */
4136 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4137 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004138 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004139 goto error;
4140 }
Radek Krejci21c81652017-01-23 10:42:55 +01004141 retval->ext = reallocated;
4142
4143 /* init memory */
4144 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004145 }
4146
Radek Krejcie534c132016-11-23 13:32:31 +01004147 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4148 if (strcmp(sub->ns->value, LY_NSYIN)) {
4149 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004150 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 +01004151 retval->ext_size++;
4152 if (ret) {
4153 goto error;
4154 }
4155 } else {
4156 ret = fill_yin_iffeature(retval, 0, sub, &choice->iffeature[choice->iffeature_size], unres);
4157 choice->iffeature_size++;
4158 if (ret) {
4159 goto error;
4160 }
4161 }
4162 }
4163
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004164 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02004165 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004166 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "default", "choice");
Michal Vasko51e5c582017-01-19 14:16:39 +01004167 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004168 goto error;
4169 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004170
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004171 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02004172 if (dflt) {
4173 GETVAL(value, dflt, "value");
4174 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004175 goto error;
4176 }
Radek Krejci629cdef2016-06-06 15:06:36 +02004177 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004178 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004179
Michal Vasko508a50d2016-09-07 14:50:33 +02004180 /* check XPath dependencies */
4181 if (choice->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4182 goto error;
4183 }
4184
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004185 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004186
4187error:
4188
Radek Krejci629cdef2016-06-06 15:06:36 +02004189 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004190 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004191
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004192 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004193}
4194
Michal Vasko0d343d12015-08-24 14:57:36 +02004195/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004196static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004197read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
4198 int valid_config, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02004199{
Radek Krejci76512572015-08-04 09:47:08 +02004200 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02004201 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004202 struct lyxml_elem *sub, *next;
4203 const char *value;
4204 int r;
4205 int f_mand = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004206 int c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004207 void *reallocated;
Radek Krejci863c2852015-06-03 15:47:11 +02004208
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004209 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01004210 if (!anyxml) {
4211 LOGMEM;
4212 return NULL;
4213 }
Radek Krejcibf2abff2016-08-23 15:51:52 +02004214 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02004215 anyxml->prev = (struct lys_node *)anyxml;
4216 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02004217
Radek Krejci07d0fb92017-01-13 14:11:05 +01004218 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4219 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004220 goto error;
4221 }
Radek Krejci863c2852015-06-03 15:47:11 +02004222
Radek Krejcia9544502015-08-14 08:24:29 +02004223 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004224
Radek Krejcic189a952016-07-11 15:27:07 +02004225 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004226 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004227 goto error;
4228 }
4229
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004230 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004231 if (strcmp(sub->ns->value, LY_NSYIN)) {
4232 /* extension */
4233 c_ext++;
4234 } else if (!strcmp(sub->name, "mandatory")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004235 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004236 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004237 goto error;
4238 }
4239 /* just checking the flags in leaf is not sufficient, we would allow
4240 * multiple mandatory statements with the "false" value
4241 */
4242 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02004243
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004244 GETVAL(value, sub, "value");
4245 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004246 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004247 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004248 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004249 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004250 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004251 goto error;
4252 }
4253 /* else false is the default value, so we can ignore it */
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004254
4255 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
4256 goto error;
4257 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004258 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004259 } else if (!strcmp(sub->name, "when")) {
4260 if (anyxml->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004261 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004262 goto error;
4263 }
4264
Radek Krejci5323b492017-01-16 15:40:11 +01004265 anyxml->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004266 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004267 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004268 goto error;
4269 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004270 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004271 } else if (!strcmp(sub->name, "must")) {
4272 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004273 } else if (!strcmp(sub->name, "if-feature")) {
4274 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02004275
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004276 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004277 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004278 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004279 }
4280 }
Radek Krejci863c2852015-06-03 15:47:11 +02004281
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004282 /* middle part - process nodes with cardinality of 0..n */
4283 if (c_must) {
4284 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004285 if (!anyxml->must) {
4286 LOGMEM;
4287 goto error;
4288 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004289 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004290 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004291 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
4292 if (!anyxml->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004293 LOGMEM;
4294 goto error;
4295 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004296 }
Radek Krejcie534c132016-11-23 13:32:31 +01004297 if (c_ext) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004298 /* some extensions may be already present from the substatements */
4299 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4300 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004301 LOGMEM;
4302 goto error;
4303 }
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004304 retval->ext = reallocated;
4305
4306 /* init memory */
4307 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004308 }
Radek Krejci863c2852015-06-03 15:47:11 +02004309
Radek Krejcie534c132016-11-23 13:32:31 +01004310 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4311 if (strcmp(sub->ns->value, LY_NSYIN)) {
4312 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004313 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 +01004314 retval->ext_size++;
4315 if (r) {
4316 goto error;
4317 }
4318 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004319 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004320 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004321 if (r) {
4322 goto error;
4323 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004324 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004325 r = fill_yin_iffeature(retval, 0, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004326 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004327 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004328 goto error;
4329 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004330 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004331 }
Radek Krejci863c2852015-06-03 15:47:11 +02004332
Michal Vasko508a50d2016-09-07 14:50:33 +02004333 /* check XPath dependencies */
4334 if ((anyxml->when || anyxml->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4335 goto error;
4336 }
4337
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004338 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02004339
4340error:
4341
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004342 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02004343
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004344 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02004345}
4346
Michal Vasko0d343d12015-08-24 14:57:36 +02004347/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004348static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004349read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004350 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004351{
Radek Krejci76512572015-08-04 09:47:08 +02004352 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004353 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004354 struct lyxml_elem *sub, *next;
4355 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01004356 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004357 int c_must = 0, c_ftrs = 0, f_mand = 0, c_ext = 0;
Radek Krejcifccd1442017-01-16 10:26:57 +01004358 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004359
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004360 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01004361 if (!leaf) {
4362 LOGMEM;
4363 return NULL;
4364 }
Radek Krejci76512572015-08-04 09:47:08 +02004365 leaf->nodetype = LYS_LEAF;
4366 leaf->prev = (struct lys_node *)leaf;
4367 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004368
Radek Krejci07d0fb92017-01-13 14:11:05 +01004369 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4370 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004371 goto error;
4372 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004373
Radek Krejcia9544502015-08-14 08:24:29 +02004374 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004375
Radek Krejcic189a952016-07-11 15:27:07 +02004376 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004377 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004378 goto error;
4379 }
4380
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004381 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004382 if (strcmp(sub->ns->value, LY_NSYIN)) {
4383 /* extension */
4384 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004385 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004386 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004387 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004388 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004389 goto error;
4390 }
Michal Vasko88c29542015-11-27 14:57:53 +01004391 /* HACK for unres */
4392 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004393 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004394 /* postpone type resolution when if-feature parsing is done since we need
4395 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004396 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004397 } else if (!strcmp(sub->name, "default")) {
4398 if (leaf->dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004399 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004400 goto error;
4401 }
4402 GETVAL(value, sub, "value");
4403 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci1abcdae2017-01-18 14:14:18 +01004404
4405 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
4406 goto error;
4407 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004408 } else if (!strcmp(sub->name, "units")) {
4409 if (leaf->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004410 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004411 goto error;
4412 }
4413 GETVAL(value, sub, "name");
4414 leaf->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004415
Radek Krejciac00b2a2017-01-17 14:05:00 +01004416 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004417 goto error;
4418 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004419 } else if (!strcmp(sub->name, "mandatory")) {
4420 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004421 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004422 goto error;
4423 }
4424 /* just checking the flags in leaf is not sufficient, we would allow
4425 * multiple mandatory statements with the "false" value
4426 */
4427 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02004428
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004429 GETVAL(value, sub, "value");
4430 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004431 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004432 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004433 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004434 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004435 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004436 goto error;
4437 } /* else false is the default value, so we can ignore it */
Radek Krejcifccd1442017-01-16 10:26:57 +01004438
Radek Krejciac00b2a2017-01-17 14:05:00 +01004439 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004440 goto error;
4441 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004442 } else if (!strcmp(sub->name, "when")) {
4443 if (leaf->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004444 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004445 goto error;
4446 }
4447
Radek Krejci5323b492017-01-16 15:40:11 +01004448 leaf->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004449 if (!leaf->when) {
4450 goto error;
4451 }
4452
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004453 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02004454 c_must++;
4455 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004456 } else if (!strcmp(sub->name, "if-feature")) {
4457 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004458 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004459
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004460 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004461 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004462 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004463 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004464
Michal Vasko88c29542015-11-27 14:57:53 +01004465 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004466 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004467
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004468 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004469 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004470 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004471 goto error;
4472 }
Michal Vasko478c4652016-07-21 12:55:01 +02004473 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004474 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "mandatory", "leaf");
Michal Vasko51e5c582017-01-19 14:16:39 +01004475 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL,
Michal Vasko478c4652016-07-21 12:55:01 +02004476 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
4477 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004478 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004479
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004480 /* middle part - process nodes with cardinality of 0..n */
4481 if (c_must) {
4482 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004483 if (!leaf->must) {
4484 LOGMEM;
4485 goto error;
4486 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004487 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004488 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004489 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
4490 if (!leaf->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004491 LOGMEM;
4492 goto error;
4493 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004494 }
Radek Krejcie534c132016-11-23 13:32:31 +01004495 if (c_ext) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004496 /* some extensions may be already present from the substatements */
4497 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4498 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004499 LOGMEM;
4500 goto error;
4501 }
Radek Krejcifccd1442017-01-16 10:26:57 +01004502 retval->ext = reallocated;
4503
4504 /* init memory */
4505 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004506 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004507
Radek Krejcie534c132016-11-23 13:32:31 +01004508 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4509 if (strcmp(sub->ns->value, LY_NSYIN)) {
4510 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004511 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 +01004512 retval->ext_size++;
4513 if (r) {
4514 goto error;
4515 }
4516 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004517 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004518 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004519 if (r) {
4520 goto error;
4521 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004522 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004523 r = fill_yin_iffeature(retval, 0, sub, &leaf->iffeature[leaf->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004524 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004525 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004526 goto error;
4527 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004528 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004529 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004530
Radek Krejcicbb473e2016-09-16 14:48:32 +02004531 /* finalize type parsing */
4532 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
4533 leaf->type.der = NULL;
4534 goto error;
4535 }
4536
4537 /* check default value (if not defined, there still could be some restrictions
4538 * that need to be checked against a default value from a derived type) */
Radek Krejci51673202016-11-01 17:00:32 +01004539 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt)) == -1) {
Radek Krejcicbb473e2016-09-16 14:48:32 +02004540 goto error;
4541 }
4542
Michal Vasko508a50d2016-09-07 14:50:33 +02004543 /* check XPath dependencies */
4544 if ((leaf->when || leaf->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4545 goto error;
4546 }
4547
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004548 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004549
4550error:
4551
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004552 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004553
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004554 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004555}
4556
Michal Vasko0d343d12015-08-24 14:57:36 +02004557/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004558static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004559read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004560 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004561{
Radek Krejci76512572015-08-04 09:47:08 +02004562 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004563 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004564 struct lyxml_elem *sub, *next;
4565 const char *value;
4566 char *endptr;
4567 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004568 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004569 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004570 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejci5323b492017-01-16 15:40:11 +01004571 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004573 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01004574 if (!llist) {
4575 LOGMEM;
4576 return NULL;
4577 }
Radek Krejci76512572015-08-04 09:47:08 +02004578 llist->nodetype = LYS_LEAFLIST;
4579 llist->prev = (struct lys_node *)llist;
4580 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004581
Radek Krejci07d0fb92017-01-13 14:11:05 +01004582 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4583 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004584 goto error;
4585 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004586
Radek Krejcia9544502015-08-14 08:24:29 +02004587 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004588
Radek Krejcic189a952016-07-11 15:27:07 +02004589 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004590 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004591 goto error;
4592 }
4593
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004594 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004595 if (strcmp(sub->ns->value, LY_NSYIN)) {
4596 /* extension */
4597 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004598 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004599 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004600 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004601 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004602 goto error;
4603 }
Michal Vasko88c29542015-11-27 14:57:53 +01004604 /* HACK for unres */
4605 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004606 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004607 /* postpone type resolution when if-feature parsing is done since we need
4608 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004609 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004610 } else if (!strcmp(sub->name, "units")) {
4611 if (llist->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004612 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004613 goto error;
4614 }
4615 GETVAL(value, sub, "name");
4616 llist->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004617
Radek Krejciac00b2a2017-01-17 14:05:00 +01004618 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004619 goto error;
4620 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004621 } else if (!strcmp(sub->name, "ordered-by")) {
4622 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004623 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004624 goto error;
4625 }
4626 /* just checking the flags in llist is not sufficient, we would
4627 * allow multiple ordered-by statements with the "system" value
4628 */
4629 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004630
Radek Krejci1574a8d2015-08-03 14:16:52 +02004631 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004632 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4633 * state data
4634 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004635 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004636 continue;
4637 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004638
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004639 GETVAL(value, sub, "value");
4640 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004641 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004642 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004643 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004644 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02004645 } /* else system is the default value, so we can ignore it */
4646
Radek Krejciac00b2a2017-01-17 14:05:00 +01004647 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
4648 goto error;
4649 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004650 } else if (!strcmp(sub->name, "must")) {
4651 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02004652 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004653 } else if (!strcmp(sub->name, "if-feature")) {
4654 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004655 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02004656 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004657 /* read the default's extension instances */
4658 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, c_dflt, unres)) {
4659 goto error;
4660 }
4661
Radek Krejcid5a5c282016-08-15 15:38:08 +02004662 c_dflt++;
4663 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004664
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004665 } else if (!strcmp(sub->name, "min-elements")) {
4666 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004667 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004668 goto error;
4669 }
4670 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004671
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004672 GETVAL(value, sub, "value");
4673 while (isspace(value[0])) {
4674 value++;
4675 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004676
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004677 /* convert it to uint32_t */
4678 errno = 0;
4679 endptr = NULL;
4680 val = strtoul(value, &endptr, 10);
4681 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004682 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004683 goto error;
4684 }
4685 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004686 if (llist->max && (llist->min > llist->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004687 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004688 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004689 goto error;
4690 }
Radek Krejci5323b492017-01-16 15:40:11 +01004691
Radek Krejciac00b2a2017-01-17 14:05:00 +01004692 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004693 goto error;
4694 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004695 } else if (!strcmp(sub->name, "max-elements")) {
4696 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004697 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004698 goto error;
4699 }
4700 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004701
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004702 GETVAL(value, sub, "value");
4703 while (isspace(value[0])) {
4704 value++;
4705 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004706
Radek Krejci0d7b2472016-02-12 11:11:03 +01004707 if (!strcmp(value, "unbounded")) {
4708 llist->max = 0;
4709 } else {
4710 /* convert it to uint32_t */
4711 errno = 0;
4712 endptr = NULL;
4713 val = strtoul(value, &endptr, 10);
4714 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004715 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004716 goto error;
4717 }
4718 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004719 if (llist->min > llist->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004720 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004721 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004722 goto error;
4723 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004724 }
Radek Krejci5323b492017-01-16 15:40:11 +01004725
Radek Krejciac00b2a2017-01-17 14:05:00 +01004726 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004727 goto error;
4728 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004729 } else if (!strcmp(sub->name, "when")) {
4730 if (llist->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004731 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004732 goto error;
4733 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004734
Radek Krejci5323b492017-01-16 15:40:11 +01004735 llist->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004736 if (!llist->when) {
4737 goto error;
4738 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004739 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004740 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004741 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004742 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004743
Michal Vasko88c29542015-11-27 14:57:53 +01004744 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004745 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004746
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004747 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004748 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004749 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004750 goto error;
4751 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004752
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004753 /* middle part - process nodes with cardinality of 0..n */
4754 if (c_must) {
4755 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004756 if (!llist->must) {
4757 LOGMEM;
4758 goto error;
4759 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004760 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004761 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004762 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
4763 if (!llist->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004764 LOGMEM;
4765 goto error;
4766 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004767 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004768 if (c_dflt) {
4769 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
4770 if (!llist->dflt) {
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004771 LOGMEM;
4772 goto error;
4773 }
4774 }
Radek Krejcie534c132016-11-23 13:32:31 +01004775 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01004776 /* some extensions may be already present from the substatements */
4777 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4778 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004779 LOGMEM;
4780 goto error;
4781 }
Radek Krejci5323b492017-01-16 15:40:11 +01004782 retval->ext = reallocated;
4783
4784 /* init memory */
4785 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004786 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004787
Radek Krejcie534c132016-11-23 13:32:31 +01004788 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4789 if (strcmp(sub->ns->value, LY_NSYIN)) {
4790 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004791 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 +01004792 retval->ext_size++;
4793 if (r) {
4794 goto error;
4795 }
4796 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004797 r = fill_yin_must(module, sub, &llist->must[llist->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004798 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004799 if (r) {
4800 goto error;
4801 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004802 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004803 r = fill_yin_iffeature(retval, 0, sub, &llist->iffeature[llist->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004804 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004805 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004806 goto error;
4807 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004808 } else if (!strcmp(sub->name, "default")) {
4809 GETVAL(value, sub, "value");
4810
Radek Krejciac1a52c2016-09-15 14:42:40 +02004811 /* check for duplicity in case of configuration data,
4812 * in case of status data duplicities are allowed */
4813 if (llist->flags & LYS_CONFIG_W) {
4814 for (r = 0; r < llist->dflt_size; r++) {
4815 if (ly_strequal(llist->dflt[r], value, 1)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004816 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, "default");
Michal Vasko51e5c582017-01-19 14:16:39 +01004817 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "Duplicated default value \"%s\".", value);
Radek Krejciac1a52c2016-09-15 14:42:40 +02004818 goto error;
4819 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004820 }
4821 }
4822 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004823 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004824 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004825
Radek Krejcicbb473e2016-09-16 14:48:32 +02004826 /* finalize type parsing */
4827 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
4828 llist->type.der = NULL;
4829 goto error;
4830 }
4831
Radek Krejcid5a5c282016-08-15 15:38:08 +02004832 if (llist->dflt_size && llist->min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004833 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "min-elements", "leaf-list");
Michal Vasko51e5c582017-01-19 14:16:39 +01004834 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02004835 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
4836 goto error;
4837 }
4838
4839 /* check default value (if not defined, there still could be some restrictions
4840 * that need to be checked against a default value from a derived type) */
4841 for (r = 0; r < llist->dflt_size; r++) {
Radek Krejci51673202016-11-01 17:00:32 +01004842 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
4843 (struct lys_node *)(&llist->dflt[r])) == -1) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02004844 goto error;
Radek Krejci25d782a2015-05-22 15:03:23 +02004845 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004846 }
4847
Michal Vasko508a50d2016-09-07 14:50:33 +02004848 /* check XPath dependencies */
4849 if ((llist->when || llist->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4850 goto error;
4851 }
4852
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004853 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004854
4855error:
4856
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004857 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004858
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004859 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004860}
4861
Michal Vasko0d343d12015-08-24 14:57:36 +02004862/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004863static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004864read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004865 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004866{
Radek Krejci1d82ef62015-08-07 14:44:40 +02004867 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02004868 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004869 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01004870 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01004871 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004872 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejci5c08a992016-11-02 13:30:04 +01004873 const char *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004874 char *auxs;
4875 unsigned long val;
Radek Krejcie36d7c72017-01-17 16:12:30 +01004876 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004878 /* init */
4879 memset(&root, 0, sizeof root);
4880 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02004881
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004882 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01004883 if (!list) {
4884 LOGMEM;
4885 return NULL;
4886 }
Radek Krejci76512572015-08-04 09:47:08 +02004887 list->nodetype = LYS_LIST;
4888 list->prev = (struct lys_node *)list;
4889 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004890
Radek Krejci07d0fb92017-01-13 14:11:05 +01004891 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4892 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004893 goto error;
4894 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004895
Radek Krejcia9544502015-08-14 08:24:29 +02004896 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4897
Radek Krejcic189a952016-07-11 15:27:07 +02004898 /* insert the node into the schema tree */
4899 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4900 goto error;
4901 }
4902
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004903 /* process list's specific children */
4904 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004905 if (strcmp(sub->ns->value, LY_NSYIN)) {
4906 /* extension */
4907 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004908 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02004909
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004910 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01004911 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004912 !strcmp(sub->name, "leaf-list") ||
4913 !strcmp(sub->name, "leaf") ||
4914 !strcmp(sub->name, "list") ||
4915 !strcmp(sub->name, "choice") ||
4916 !strcmp(sub->name, "uses") ||
4917 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004918 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02004919 !strcmp(sub->name, "action") ||
4920 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004921 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004922 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004923
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004924 /* array counters */
4925 } else if (!strcmp(sub->name, "key")) {
4926 /* check cardinality 0..1 */
4927 if (list->keys_size) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004928 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004929 goto error;
4930 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004931
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004932 /* count the number of keys */
4933 GETVAL(value, sub, "value");
Radek Krejci5c08a992016-11-02 13:30:04 +01004934 list->keys_str = lydict_insert(module->ctx, value, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004935 while ((value = strpbrk(value, " \t\n"))) {
4936 list->keys_size++;
4937 while (isspace(*value)) {
4938 value++;
4939 }
4940 }
4941 list->keys_size++;
4942 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01004943 if (!list->keys) {
4944 LOGMEM;
4945 goto error;
4946 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01004947
4948 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_KEY, 0, unres)) {
4949 goto error;
4950 }
4951 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004952 } else if (!strcmp(sub->name, "unique")) {
4953 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02004954 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004955 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004956 } else if (!strcmp(sub->name, "typedef")) {
4957 c_tpdf++;
4958 } else if (!strcmp(sub->name, "must")) {
4959 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004960 } else if (!strcmp(sub->name, "if-feature")) {
4961 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02004962
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004963 /* optional stetments */
4964 } else if (!strcmp(sub->name, "ordered-by")) {
4965 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004966 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004967 goto error;
4968 }
4969 /* just checking the flags in llist is not sufficient, we would
4970 * allow multiple ordered-by statements with the "system" value
4971 */
4972 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004973
Radek Krejci1574a8d2015-08-03 14:16:52 +02004974 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004975 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4976 * state data
4977 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004978 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004979 continue;
4980 }
Radek Krejci345ad742015-06-03 11:04:18 +02004981
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004982 GETVAL(value, sub, "value");
4983 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004984 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004985 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004986 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004987 goto error;
Radek Krejcie36d7c72017-01-17 16:12:30 +01004988 } /* else system is the default value, so we can ignore it */
4989
4990 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
4991 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004992 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004993 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004994 } else if (!strcmp(sub->name, "min-elements")) {
4995 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004996 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004997 goto error;
4998 }
4999 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005000
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005001 GETVAL(value, sub, "value");
5002 while (isspace(value[0])) {
5003 value++;
5004 }
Radek Krejci345ad742015-06-03 11:04:18 +02005005
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005006 /* convert it to uint32_t */
5007 errno = 0;
5008 auxs = NULL;
5009 val = strtoul(value, &auxs, 10);
5010 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005011 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005012 goto error;
5013 }
5014 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005015 if (list->max && (list->min > list->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005016 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01005017 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005018 lyxml_free(module->ctx, sub);
5019 goto error;
5020 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005021 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
5022 goto error;
5023 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005024 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005025 } else if (!strcmp(sub->name, "max-elements")) {
5026 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005027 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005028 goto error;
5029 }
5030 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005031
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005032 GETVAL(value, sub, "value");
5033 while (isspace(value[0])) {
5034 value++;
5035 }
Radek Krejci345ad742015-06-03 11:04:18 +02005036
Radek Krejci0d7b2472016-02-12 11:11:03 +01005037 if (!strcmp(value, "unbounded")) {
5038 list->max = 0;;
5039 } else {
5040 /* convert it to uint32_t */
5041 errno = 0;
5042 auxs = NULL;
5043 val = strtoul(value, &auxs, 10);
5044 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005045 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01005046 goto error;
5047 }
5048 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005049 if (list->min > list->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005050 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01005051 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005052 goto error;
5053 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005054 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005055 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
5056 goto error;
5057 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005058 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005059 } else if (!strcmp(sub->name, "when")) {
5060 if (list->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005061 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005062 goto error;
5063 }
5064
Radek Krejci5323b492017-01-16 15:40:11 +01005065 list->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005066 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005067 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005068 goto error;
5069 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005070 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005071 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005072 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005073 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005074 }
5075 }
Radek Krejci345ad742015-06-03 11:04:18 +02005076
Michal Vaskoe022a562016-09-27 14:24:15 +02005077 /* check - if list is configuration, key statement is mandatory
5078 * (but only if we are not in a grouping or augment, then the check is deferred) */
5079 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT)); node = node->parent);
Radek Krejci5c08a992016-11-02 13:30:04 +01005080 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys_str) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005081 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005082 goto error;
5083 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005084
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005085 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5086 if (c_tpdf) {
5087 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005088 if (!list->tpdf) {
5089 LOGMEM;
5090 goto error;
5091 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005092 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005093 if (c_must) {
5094 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01005095 if (!list->must) {
5096 LOGMEM;
5097 goto error;
5098 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005099 }
5100 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005101 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
5102 if (!list->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005103 LOGMEM;
5104 goto error;
5105 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005106 }
Radek Krejcie534c132016-11-23 13:32:31 +01005107 if (c_ext) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005108 /* some extensions may be already present from the substatements */
5109 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5110 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005111 LOGMEM;
5112 goto error;
5113 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005114 retval->ext = reallocated;
5115
5116 /* init memory */
5117 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005118 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005119
Radek Krejcie534c132016-11-23 13:32:31 +01005120 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5121 if (strcmp(sub->ns->value, LY_NSYIN)) {
5122 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005123 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 +01005124 retval->ext_size++;
5125 if (r) {
5126 goto error;
5127 }
5128 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005129 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
5130 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005131 if (r) {
5132 goto error;
5133 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005134 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005135 r = fill_yin_iffeature(retval, 0, sub, &list->iffeature[list->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005136 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005137 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005138 goto error;
5139 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005140 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005141 r = fill_yin_must(module, sub, &list->must[list->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005142 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005143 if (r) {
5144 goto error;
5145 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005146 }
5147 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005148
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005149 /* last part - process data nodes */
5150 LY_TREE_FOR_SAFE(root.child, next, sub) {
5151 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005152 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005153 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005154 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005155 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005156 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005157 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005158 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005159 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005160 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005161 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005162 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005163 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005164 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005165 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005166 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005167 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005168 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005169 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005170 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005171 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005172 node = read_yin_notif(module, retval, sub, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005173 } else {
5174 LOGINT;
5175 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005176 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005177 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005178 goto error;
5179 }
Radek Krejci73adb602015-07-02 18:07:40 +02005180
Michal Vasko345da0a2015-12-02 10:35:55 +01005181 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005182 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005183
Radek Krejci5c08a992016-11-02 13:30:04 +01005184 if (list->keys_str) {
5185 /* check that we are not in grouping */
5186 for (node = parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
5187 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01005188 goto error;
5189 }
5190 } /* 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 +02005191
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005192 /* process unique statements */
5193 if (c_uniq) {
5194 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01005195 if (!list->unique) {
5196 LOGMEM;
5197 goto error;
5198 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005199
Radek Krejci461efb92016-02-12 15:52:18 +01005200 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
5201 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
5202 list->unique_size++;
5203 if (r) {
5204 goto error;
5205 }
5206
Radek Krejcie36d7c72017-01-17 16:12:30 +01005207 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub,
5208 LYEXT_SUBSTMT_UNIQUE, list->unique_size - 1, unres)) {
5209 goto error;
5210 }
Radek Krejci461efb92016-02-12 15:52:18 +01005211 lyxml_free(module->ctx, sub);
5212 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005213 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005214
Michal Vasko508a50d2016-09-07 14:50:33 +02005215 /* check XPath dependencies */
5216 if ((list->when || list->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5217 goto error;
5218 }
5219
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005220 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005221
5222error:
5223
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005224 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005225 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005226 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005227 }
5228 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005229 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005230 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005231
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005232 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005233}
5234
Michal Vasko0d343d12015-08-24 14:57:36 +02005235/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005236static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005237read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02005238 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005239{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005240 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005241 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005242 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005243 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005244 const char *value;
Radek Krejci07d0fb92017-01-13 14:11:05 +01005245 void *reallocated;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005246 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005247 int c_tpdf = 0, c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005248
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005249 /* init */
5250 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005251
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005252 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01005253 if (!cont) {
5254 LOGMEM;
5255 return NULL;
5256 }
Radek Krejci76512572015-08-04 09:47:08 +02005257 cont->nodetype = LYS_CONTAINER;
5258 cont->prev = (struct lys_node *)cont;
5259 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005260
Radek Krejci07d0fb92017-01-13 14:11:05 +01005261 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
5262 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005263 goto error;
5264 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005265
Radek Krejcia9544502015-08-14 08:24:29 +02005266 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5267
Radek Krejcic189a952016-07-11 15:27:07 +02005268 /* insert the node into the schema tree */
5269 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5270 goto error;
5271 }
5272
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005273 /* process container's specific children */
5274 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005275 if (strcmp(sub->ns->value, LY_NSYIN)) {
5276 /* extension */
5277 c_ext++;
5278 } else if (!strcmp(sub->name, "presence")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005279 if (cont->presence) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005280 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005281 goto error;
5282 }
5283 GETVAL(value, sub, "value");
5284 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02005285
Radek Krejciac00b2a2017-01-17 14:05:00 +01005286 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005287 goto error;
5288 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005289 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005290 } else if (!strcmp(sub->name, "when")) {
5291 if (cont->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005292 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005293 goto error;
5294 }
5295
Radek Krejci5323b492017-01-16 15:40:11 +01005296 cont->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005297 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005298 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005299 goto error;
5300 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005301 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02005302
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005303 /* data statements */
5304 } else if (!strcmp(sub->name, "container") ||
5305 !strcmp(sub->name, "leaf-list") ||
5306 !strcmp(sub->name, "leaf") ||
5307 !strcmp(sub->name, "list") ||
5308 !strcmp(sub->name, "choice") ||
5309 !strcmp(sub->name, "uses") ||
5310 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005311 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005312 !strcmp(sub->name, "action") ||
5313 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005314 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005315 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005316
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005317 /* array counters */
5318 } else if (!strcmp(sub->name, "typedef")) {
5319 c_tpdf++;
5320 } else if (!strcmp(sub->name, "must")) {
5321 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005322 } else if (!strcmp(sub->name, "if-feature")) {
5323 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005324 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005325 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005326 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005327 }
5328 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005329
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005330 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5331 if (c_tpdf) {
5332 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005333 if (!cont->tpdf) {
5334 LOGMEM;
5335 goto error;
5336 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005337 }
5338 if (c_must) {
5339 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01005340 if (!cont->must) {
5341 LOGMEM;
5342 goto error;
5343 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005344 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005345 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005346 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
5347 if (!cont->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005348 LOGMEM;
5349 goto error;
5350 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005351 }
Radek Krejcie534c132016-11-23 13:32:31 +01005352 if (c_ext) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01005353 /* some extensions may be already present from the substatements */
5354 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5355 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005356 LOGMEM;
5357 goto error;
5358 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01005359 retval->ext = reallocated;
5360
5361 /* init memory */
5362 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005363 }
Radek Krejci800af702015-06-02 13:46:01 +02005364
Radek Krejcie534c132016-11-23 13:32:31 +01005365 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5366 if (strcmp(sub->ns->value, LY_NSYIN)) {
5367 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005368 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 +01005369 retval->ext_size++;
5370 if (r) {
5371 goto error;
5372 }
5373 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005374 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
5375 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005376 if (r) {
5377 goto error;
5378 }
5379 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005380 r = fill_yin_must(module, sub, &cont->must[cont->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005381 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005382 if (r) {
5383 goto error;
5384 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005385 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005386 r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005387 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005388 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005389 goto error;
5390 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005391 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005392 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005393
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005394 /* last part - process data nodes */
5395 LY_TREE_FOR_SAFE(root.child, next, sub) {
5396 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005397 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005398 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005399 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005400 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005401 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005402 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005403 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005404 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005405 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005406 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005407 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005408 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005409 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005410 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005411 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005412 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005413 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005414 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005415 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005416 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005417 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005418 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005419 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005420 goto error;
5421 }
Radek Krejci73adb602015-07-02 18:07:40 +02005422
Michal Vasko345da0a2015-12-02 10:35:55 +01005423 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005424 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005425
Michal Vasko508a50d2016-09-07 14:50:33 +02005426 /* check XPath dependencies */
5427 if ((cont->when || cont->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5428 goto error;
5429 }
5430
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005431 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005432
5433error:
5434
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005435 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005436 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005437 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005438 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005439
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005440 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005441}
5442
Michal Vasko0d343d12015-08-24 14:57:36 +02005443/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005444static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005445read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02005446 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005447{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005448 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005449 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005450 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005451 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005452 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005453 int c_tpdf = 0, c_ext = 0;
Radek Krejcifdc0d702017-01-23 15:58:38 +01005454 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005455
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005456 /* init */
5457 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005458
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005459 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01005460 if (!grp) {
5461 LOGMEM;
5462 return NULL;
5463 }
Radek Krejci76512572015-08-04 09:47:08 +02005464 grp->nodetype = LYS_GROUPING;
5465 grp->prev = (struct lys_node *)grp;
5466 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005467
Radek Krejci07d0fb92017-01-13 14:11:05 +01005468 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE , unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005469 goto error;
5470 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005471
Radek Krejcia9544502015-08-14 08:24:29 +02005472 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5473
Radek Krejcic189a952016-07-11 15:27:07 +02005474 /* insert the node into the schema tree */
5475 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5476 goto error;
5477 }
5478
Radek Krejci1d82ef62015-08-07 14:44:40 +02005479 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005480 if (strcmp(sub->ns->value, LY_NSYIN)) {
5481 /* extension */
5482 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005484 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005485 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005486 !strcmp(sub->name, "leaf-list") ||
5487 !strcmp(sub->name, "leaf") ||
5488 !strcmp(sub->name, "list") ||
5489 !strcmp(sub->name, "choice") ||
5490 !strcmp(sub->name, "uses") ||
5491 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005492 !strcmp(sub->name, "anyxml") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02005493 !strcmp(sub->name, "action") ||
5494 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005495 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005496 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005497
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005498 /* array counters */
5499 } else if (!strcmp(sub->name, "typedef")) {
5500 c_tpdf++;
5501 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005502 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005503 goto error;
5504 }
5505 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005506
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005507 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5508 if (c_tpdf) {
5509 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005510 if (!grp->tpdf) {
5511 LOGMEM;
5512 goto error;
5513 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005514 }
Radek Krejcie534c132016-11-23 13:32:31 +01005515 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01005516 /* some extensions may be already present from the substatements */
5517 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5518 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005519 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02005520 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005521 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01005522 retval->ext = reallocated;
5523
5524 /* init memory */
5525 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005526 }
Radek Krejcie534c132016-11-23 13:32:31 +01005527 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5528 if (strcmp(sub->ns->value, LY_NSYIN)) {
5529 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005530 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 +01005531 retval->ext_size++;
5532 if (r) {
5533 goto error;
5534 }
5535 } else {
5536 /* typedef */
5537 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
5538 grp->tpdf_size++;
5539 if (r) {
5540 goto error;
5541 }
5542 }
5543 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005544
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005545 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02005546 if (!root.child) {
5547 LOGWRN("Grouping \"%s\" without children.", retval->name);
5548 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005549 LY_TREE_FOR_SAFE(root.child, next, sub) {
5550 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005551 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005552 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005553 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005554 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005555 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005556 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005557 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005558 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005559 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005560 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005561 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005562 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005563 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005564 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005565 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005566 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005567 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005568 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005569 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02005570 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005571 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005572 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005573 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005574 goto error;
5575 }
Radek Krejci73adb602015-07-02 18:07:40 +02005576
Michal Vasko345da0a2015-12-02 10:35:55 +01005577 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005578 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005579
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005580 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005581
5582error:
5583
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005584 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005585 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005586 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005587 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005588
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005589 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005590}
5591
Michal Vasko0d343d12015-08-24 14:57:36 +02005592/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005593static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005594read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02005595 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005596{
Radek Krejcie0674f82015-06-15 13:58:51 +02005597 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005598 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02005599 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02005600 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005601 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005602 int c_tpdf = 0, c_must = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005603
Radek Krejcie0674f82015-06-15 13:58:51 +02005604 /* init */
5605 memset(&root, 0, sizeof root);
5606
Michal Vasko38d01f72015-06-15 09:41:06 +02005607 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01005608 if (!inout) {
5609 LOGMEM;
5610 return NULL;
5611 }
Radek Krejci6acc8012015-08-13 09:07:04 +02005612 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005613
5614 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02005615 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005616 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005617 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02005618 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005619 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005620 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02005621 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02005622 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02005623 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005624 }
5625
Radek Krejci76512572015-08-04 09:47:08 +02005626 retval = (struct lys_node *)inout;
Radek Krejcie7770892017-01-24 13:18:01 +01005627 retval->module = module;
Michal Vaskoebeac942015-06-15 12:11:50 +02005628
Radek Krejcia9544502015-08-14 08:24:29 +02005629 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5630
Radek Krejcic189a952016-07-11 15:27:07 +02005631 /* insert the node into the schema tree */
5632 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5633 goto error;
5634 }
5635
Michal Vasko38d01f72015-06-15 09:41:06 +02005636 /* data statements */
5637 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie7770892017-01-24 13:18:01 +01005638 if (!sub->ns) {
5639 /* garbage */
5640 lyxml_free(module->ctx, sub);
5641 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01005642 /* extension */
5643 c_ext++;
5644 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005645 !strcmp(sub->name, "leaf-list") ||
5646 !strcmp(sub->name, "leaf") ||
5647 !strcmp(sub->name, "list") ||
5648 !strcmp(sub->name, "choice") ||
5649 !strcmp(sub->name, "uses") ||
5650 !strcmp(sub->name, "grouping") ||
5651 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005652 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005653 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005654
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005655 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005656 } else if (!strcmp(sub->name, "typedef")) {
5657 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02005658
Radek Krejci1a31efe2016-07-29 11:04:16 +02005659 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005660 c_must++;
5661
Michal Vasko38d01f72015-06-15 09:41:06 +02005662 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005663 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005664 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005665 }
5666 }
5667
5668 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5669 if (c_tpdf) {
5670 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005671 if (!inout->tpdf) {
5672 LOGMEM;
5673 goto error;
5674 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005675 }
Radek Krejci19332802016-07-29 10:39:46 +02005676 if (c_must) {
5677 inout->must = calloc(c_must, sizeof *inout->must);
5678 if (!inout->must) {
5679 LOGMEM;
5680 goto error;
5681 }
5682 }
Radek Krejcie534c132016-11-23 13:32:31 +01005683 if (c_ext) {
5684 inout->ext = calloc(c_ext, sizeof *inout->ext);
5685 if (!inout->ext) {
5686 LOGMEM;
5687 goto error;
5688 }
5689 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005690
Radek Krejcie534c132016-11-23 13:32:31 +01005691 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5692 if (strcmp(sub->ns->value, LY_NSYIN)) {
5693 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005694 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 +01005695 retval->ext_size++;
5696 if (r) {
5697 goto error;
5698 }
5699 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005700 r = fill_yin_must(module, sub, &inout->must[inout->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02005701 inout->must_size++;
5702 if (r) {
5703 goto error;
5704 }
5705 } else { /* typedef */
5706 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
5707 inout->tpdf_size++;
5708 if (r) {
5709 goto error;
5710 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005711 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005712 }
5713
5714 /* last part - process data nodes */
5715 LY_TREE_FOR_SAFE(root.child, next, sub) {
5716 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005717 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005718 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005719 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005720 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005721 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005722 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005723 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005724 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005725 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005726 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005727 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005728 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005729 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005730 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005731 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005732 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005733 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005734 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005735 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005736 goto error;
5737 }
Radek Krejci73adb602015-07-02 18:07:40 +02005738
Michal Vasko345da0a2015-12-02 10:35:55 +01005739 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005740 }
5741
Michal Vasko508a50d2016-09-07 14:50:33 +02005742 /* check XPath dependencies */
5743 if (inout->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5744 goto error;
5745 }
5746
Michal Vasko38d01f72015-06-15 09:41:06 +02005747 return retval;
5748
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005749error:
Michal Vasko38d01f72015-06-15 09:41:06 +02005750
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005751 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02005752 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005753 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005754 }
5755
5756 return NULL;
5757}
5758
Michal Vasko0d343d12015-08-24 14:57:36 +02005759/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005760static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005761read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02005762 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02005763{
Michal Vaskoc6551b32015-06-16 10:51:43 +02005764 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005765 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005766 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005767 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005768 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005769 int c_tpdf = 0, c_ftrs = 0, c_must = 0, c_ext = 0;
Radek Krejci478ef1d2017-01-24 13:56:09 +01005770 void *reallocated;
Michal Vasko0ea41032015-06-16 08:53:55 +02005771
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005772 if (parent && (module->version < 2)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005773 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "notification");
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005774 return NULL;
5775 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005776
Michal Vaskoc6551b32015-06-16 10:51:43 +02005777 memset(&root, 0, sizeof root);
5778
Michal Vasko0ea41032015-06-16 08:53:55 +02005779 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01005780 if (!notif) {
5781 LOGMEM;
5782 return NULL;
5783 }
Radek Krejci76512572015-08-04 09:47:08 +02005784 notif->nodetype = LYS_NOTIF;
5785 notif->prev = (struct lys_node *)notif;
5786 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005787
Radek Krejci07d0fb92017-01-13 14:11:05 +01005788 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005789 goto error;
5790 }
5791
Radek Krejcia9544502015-08-14 08:24:29 +02005792 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5793
Radek Krejcic189a952016-07-11 15:27:07 +02005794 /* insert the node into the schema tree */
5795 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5796 goto error;
5797 }
5798
Michal Vasko0ea41032015-06-16 08:53:55 +02005799 /* process rpc's specific children */
5800 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005801 if (strcmp(sub->ns->value, LY_NSYIN)) {
5802 /* extension */
5803 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005804 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02005805
Michal Vasko0ea41032015-06-16 08:53:55 +02005806 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005807 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005808 !strcmp(sub->name, "leaf-list") ||
5809 !strcmp(sub->name, "leaf") ||
5810 !strcmp(sub->name, "list") ||
5811 !strcmp(sub->name, "choice") ||
5812 !strcmp(sub->name, "uses") ||
5813 !strcmp(sub->name, "grouping") ||
5814 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005815 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005816 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02005817
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005818 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02005819 } else if (!strcmp(sub->name, "typedef")) {
5820 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005821 } else if (!strcmp(sub->name, "if-feature")) {
5822 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02005823 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005824 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02005825 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005826 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02005827 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02005828 }
5829 }
5830
5831 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5832 if (c_tpdf) {
5833 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005834 if (!notif->tpdf) {
5835 LOGMEM;
5836 goto error;
5837 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005838 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005839 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005840 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
5841 if (!notif->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005842 LOGMEM;
5843 goto error;
5844 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005845 }
Radek Krejci19332802016-07-29 10:39:46 +02005846 if (c_must) {
5847 notif->must = calloc(c_must, sizeof *notif->must);
5848 if (!notif->must) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005849 LOGMEM;
5850 goto error;
5851 }
5852 }
Radek Krejcie534c132016-11-23 13:32:31 +01005853 if (c_ext) {
Radek Krejci478ef1d2017-01-24 13:56:09 +01005854 /* some extensions may be already present from the substatements */
5855 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5856 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005857 LOGMEM;
5858 goto error;
5859 }
Radek Krejci478ef1d2017-01-24 13:56:09 +01005860 retval->ext = reallocated;
5861
5862 /* init memory */
5863 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005864 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005865
Radek Krejcie534c132016-11-23 13:32:31 +01005866 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5867 if (strcmp(sub->ns->value, LY_NSYIN)) {
5868 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005869 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 +01005870 retval->ext_size++;
5871 if (r) {
5872 goto error;
5873 }
5874 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005875 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
5876 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02005877 if (r) {
5878 goto error;
5879 }
Radek Krejci96299152016-06-22 10:17:50 +02005880 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005881 r = fill_yin_iffeature(retval, 0, sub, &notif->iffeature[notif->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005882 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005883 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005884 goto error;
5885 }
Radek Krejci19332802016-07-29 10:39:46 +02005886 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005887 r = fill_yin_must(module, sub, &notif->must[notif->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02005888 notif->must_size++;
Radek Krejci0b24d752015-07-02 15:02:27 +02005889 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005890 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005891 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005892 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005893 }
5894
5895 /* last part - process data nodes */
5896 LY_TREE_FOR_SAFE(root.child, next, sub) {
5897 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005898 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005899 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005900 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005901 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005902 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005903 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005904 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005905 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005906 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005907 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005908 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005909 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005910 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005911 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005912 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005913 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005914 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005915 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005916 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005917 goto error;
5918 }
Radek Krejci73adb602015-07-02 18:07:40 +02005919
Michal Vasko345da0a2015-12-02 10:35:55 +01005920 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02005921 }
5922
Michal Vasko508a50d2016-09-07 14:50:33 +02005923 /* check XPath dependencies */
5924 if (notif->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5925 goto error;
5926 }
5927
Michal Vasko0ea41032015-06-16 08:53:55 +02005928 return retval;
5929
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005930error:
Michal Vasko0ea41032015-06-16 08:53:55 +02005931
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005932 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02005933 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005934 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02005935 }
5936
5937 return NULL;
5938}
5939
Michal Vasko0d343d12015-08-24 14:57:36 +02005940/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005941static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005942read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005943 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005944{
Radek Krejcie0674f82015-06-15 13:58:51 +02005945 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005946 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005947 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02005948 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02005949 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005950 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0, c_ext = 0;
Radek Krejci94596cf2017-01-24 13:19:16 +01005951 void *reallocated;
Michal Vasko38d01f72015-06-15 09:41:06 +02005952
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005953 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02005954 if (module->version < 2) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005955 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "action");
Michal Vaskobb174852016-07-25 11:00:21 +02005956 return NULL;
5957 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005958 for (node = parent; node; node = lys_parent(node)) {
Radek Krejcia3b19f72016-09-30 13:02:45 +02005959 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005960 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005961 LOGVAL(LYE_INPAR, LY_VLOG_LYS, parent, strnodetype(node->nodetype), "action");
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005962 return NULL;
5963 }
5964 }
5965 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005966
Radek Krejcie0674f82015-06-15 13:58:51 +02005967 /* init */
5968 memset(&root, 0, sizeof root);
5969
Michal Vasko38d01f72015-06-15 09:41:06 +02005970 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01005971 if (!rpc) {
5972 LOGMEM;
5973 return NULL;
5974 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005975 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02005976 rpc->prev = (struct lys_node *)rpc;
5977 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02005978
Radek Krejci07d0fb92017-01-13 14:11:05 +01005979 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005980 goto error;
5981 }
5982
Radek Krejcia9544502015-08-14 08:24:29 +02005983 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5984
Radek Krejcic189a952016-07-11 15:27:07 +02005985 /* insert the node into the schema tree */
5986 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5987 goto error;
5988 }
5989
Michal Vasko38d01f72015-06-15 09:41:06 +02005990 /* process rpc's specific children */
5991 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005992 if (strcmp(sub->ns->value, LY_NSYIN)) {
5993 /* extension */
5994 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005995 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01005996 } else if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02005997 if (c_input) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005998 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005999 goto error;
6000 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006001 c_input++;
Michal Vaskof3930de2015-10-22 12:03:59 +02006002 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006003 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006004 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006005 if (c_output) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006006 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006007 goto error;
6008 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006009 c_output++;
Michal Vaskof3930de2015-10-22 12:03:59 +02006010 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006011 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006012
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006013 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02006014 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02006015 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006016 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006018 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02006019 } else if (!strcmp(sub->name, "typedef")) {
6020 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006021 } else if (!strcmp(sub->name, "if-feature")) {
6022 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006023 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006024 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006025 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02006026 }
6027 }
6028
6029 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6030 if (c_tpdf) {
6031 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01006032 if (!rpc->tpdf) {
6033 LOGMEM;
6034 goto error;
6035 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006036 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006037 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006038 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
6039 if (!rpc->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01006040 LOGMEM;
6041 goto error;
6042 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006043 }
Radek Krejcie534c132016-11-23 13:32:31 +01006044 if (c_ext) {
Radek Krejci94596cf2017-01-24 13:19:16 +01006045 /* some extensions may be already present from the substatements */
6046 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
6047 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01006048 LOGMEM;
6049 goto error;
6050 }
Radek Krejci94596cf2017-01-24 13:19:16 +01006051 retval->ext = reallocated;
6052
6053 /* init memory */
6054 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006055 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006056
Radek Krejcie534c132016-11-23 13:32:31 +01006057 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6058 if (strcmp(sub->ns->value, LY_NSYIN)) {
6059 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006060 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 +01006061 retval->ext_size++;
6062 if (r) {
6063 goto error;
6064 }
6065 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006066 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
6067 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006068 if (r) {
6069 goto error;
6070 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006071 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006072 r = fill_yin_iffeature(retval, 0, sub, &rpc->iffeature[rpc->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006073 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006074 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006075 goto error;
6076 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006077 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006078 }
6079
6080 /* last part - process data nodes */
6081 LY_TREE_FOR_SAFE(root.child, next, sub) {
6082 if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006083 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006084 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006085 node = read_yin_input_output(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006086 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006087 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006088 goto error;
6089 }
Radek Krejci73adb602015-07-02 18:07:40 +02006090
Michal Vasko345da0a2015-12-02 10:35:55 +01006091 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006092 }
6093
Michal Vasko38d01f72015-06-15 09:41:06 +02006094 return retval;
6095
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006096error:
Michal Vasko38d01f72015-06-15 09:41:06 +02006097
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006098 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006099 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006100 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006101 }
6102
6103 return NULL;
6104}
6105
Michal Vasko0d343d12015-08-24 14:57:36 +02006106/* logs directly
6107 *
Radek Krejci74705112015-06-05 10:25:44 +02006108 * resolve - referenced grouping should be bounded to the namespace (resolved)
6109 * only when uses does not appear in grouping. In a case of grouping's uses,
6110 * we just get information but we do not apply augment or refine to it.
6111 */
Radek Krejci76512572015-08-04 09:47:08 +02006112static struct lys_node *
Radek Krejci3440cc52016-06-23 17:03:59 +02006113read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02006114{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006115 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02006116 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006117 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006118 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01006119 int c_ref = 0, c_aug = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006120 int r;
Radek Krejcifdc0d702017-01-23 15:58:38 +01006121 void *reallocated;
Radek Krejci74705112015-06-05 10:25:44 +02006122
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006123 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01006124 if (!uses) {
6125 LOGMEM;
6126 return NULL;
6127 }
Radek Krejci76512572015-08-04 09:47:08 +02006128 uses->nodetype = LYS_USES;
6129 uses->prev = (struct lys_node *)uses;
6130 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02006131
Radek Krejcia9544502015-08-14 08:24:29 +02006132 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006133 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02006134
Radek Krejci07d0fb92017-01-13 14:11:05 +01006135 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006136 goto error;
6137 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006138
Radek Krejcia9544502015-08-14 08:24:29 +02006139 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
6140
Radek Krejcic189a952016-07-11 15:27:07 +02006141 /* insert the node into the schema tree */
6142 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6143 goto error;
6144 }
6145
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006146 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02006147 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006148 if (strcmp(sub->ns->value, LY_NSYIN)) {
6149 /* extension */
6150 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006151 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006152 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006153 c_ref++;
6154 } else if (!strcmp(sub->name, "augment")) {
6155 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006156 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02006157 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006158 } else if (!strcmp(sub->name, "when")) {
6159 if (uses->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006160 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006161 goto error;
6162 }
6163
Radek Krejci5323b492017-01-16 15:40:11 +01006164 uses->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006165 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006166 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006167 goto error;
6168 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006169 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006170 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006171 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006172 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006173 }
6174 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006175
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006176 /* process properties with cardinality 0..n */
6177 if (c_ref) {
6178 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01006179 if (!uses->refine) {
6180 LOGMEM;
6181 goto error;
6182 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006183 }
6184 if (c_aug) {
6185 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01006186 if (!uses->augment) {
6187 LOGMEM;
6188 goto error;
6189 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006190 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006191 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006192 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
6193 if (!uses->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01006194 LOGMEM;
6195 goto error;
6196 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006197 }
Radek Krejcie534c132016-11-23 13:32:31 +01006198 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01006199 /* some extensions may be already present from the substatements */
6200 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
6201 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01006202 LOGMEM;
6203 goto error;
6204 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01006205 retval->ext = reallocated;
6206
6207 /* init memory */
6208 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006209 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006210
Radek Krejcie534c132016-11-23 13:32:31 +01006211 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6212 if (strcmp(sub->ns->value, LY_NSYIN)) {
6213 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006214 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 +01006215 retval->ext_size++;
6216 if (r) {
6217 goto error;
6218 }
6219 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02006220 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006221 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006222 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006223 goto error;
6224 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006225 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006226 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
6227 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006228 if (r) {
6229 goto error;
6230 }
6231 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006232 r = fill_yin_iffeature(retval, 0, sub, &uses->iffeature[uses->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006233 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006234 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006235 goto error;
6236 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006237 }
6238 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006239
Radek Krejci48464ed2016-03-17 15:44:09 +01006240 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006241 goto error;
6242 }
Radek Krejci74705112015-06-05 10:25:44 +02006243
Michal Vasko508a50d2016-09-07 14:50:33 +02006244 /* check XPath dependencies */
6245 if (uses->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
6246 goto error;
6247 }
6248
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006249 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006250
6251error:
6252
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006253 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006254
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006255 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006256}
6257
Michal Vasko0d343d12015-08-24 14:57:36 +02006258/* logs directly
6259 *
6260 * common code for yin_read_module() and yin_read_submodule()
6261 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006262static int
Radek Krejcic071c542016-01-27 14:57:51 +01006263read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
6264 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02006265{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006266 struct ly_ctx *ctx = module->ctx;
Radek Krejci95f22ae2017-01-20 14:25:53 +01006267 struct lyxml_elem *next, *child, *next2, *child2, root, grps, augs, exts;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006268 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006269 struct lys_module *trg;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006270 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01006271 int i, r;
Radek Krejcic071c542016-01-27 14:57:51 +01006272 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006273 /* counters */
Radek Krejcie534c132016-11-23 13:32:31 +01006274 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;
6275 int c_ext = 0, c_extinst = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01006276 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006277
Radek Krejcic071c542016-01-27 14:57:51 +01006278 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02006279 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01006280
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006281 /* init */
6282 memset(&root, 0, sizeof root);
6283 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006284 memset(&augs, 0, sizeof augs);
Radek Krejcie534c132016-11-23 13:32:31 +01006285 memset(&exts, 0, sizeof exts);
Radek Krejcie0674f82015-06-15 13:58:51 +02006286
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006287 /*
6288 * in the first run, we process elements with cardinality of 1 or 0..1 and
6289 * count elements with cardinality 0..n. Data elements (choices, containers,
6290 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
6291 * need have all top-level and groupings already prepared at that time. In
6292 * the middle loop, we process other elements with carinality of 0..n since
6293 * we need to allocate arrays to store them.
6294 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006295 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01006296 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02006297 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01006298 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006299 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006300 } else if (strcmp(child->ns->value, LY_NSYIN)) {
6301 /* possible extension instance */
6302 lyxml_unlink_elem(module->ctx, child, 2);
6303 lyxml_add_child(module->ctx, &exts, child);
6304 c_extinst++;
6305 } else if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006306 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006307 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006308 goto error;
6309 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006310 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006311 module->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006312
6313 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_NAMESPACE, 0, unres)) {
6314 goto error;
6315 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006316 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006317 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006318 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006319 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006320 goto error;
6321 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006322 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01006323 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006324 goto error;
6325 }
6326 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006327
6328 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
6329 goto error;
6330 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006331 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006332 } else if (submodule && !strcmp(child->name, "belongs-to")) {
6333 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006334 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006335 goto error;
6336 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006337 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01006338 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006339 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006340 goto error;
6341 }
Radek Krejcif3886932015-06-04 17:36:06 +02006342
Radek Krejci95f22ae2017-01-20 14:25:53 +01006343 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_BELONGSTO, 0, unres)) {
6344 goto error;
6345 }
6346
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006347 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006348 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006349 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006350 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006351 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006352 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006353 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006354 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006355 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006356 goto error;
6357 }
6358 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006359 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006360 /* check here differs from a generic prefix check, since this prefix
6361 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02006362 */
Radek Krejci48464ed2016-03-17 15:44:09 +01006363 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006364 goto error;
6365 }
Radek Krejcic071c542016-01-27 14:57:51 +01006366 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02006367
Radek Krejci95f22ae2017-01-20 14:25:53 +01006368 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child->child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
6369 goto error;
6370 }
6371
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006372 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01006373 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02006374
6375 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006376 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006377 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006378 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006379 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006380 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006381 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006382 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006383 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006384 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006385 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006386 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02006387 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006388 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01006389 lyxml_unlink_elem(ctx, child, 2);
6390 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006391
Radek Krejci1d82ef62015-08-07 14:44:40 +02006392 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006393 c_ftrs++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006395 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006396 } else if (!strcmp(child->name, "container") ||
6397 !strcmp(child->name, "leaf-list") ||
6398 !strcmp(child->name, "leaf") ||
6399 !strcmp(child->name, "list") ||
6400 !strcmp(child->name, "choice") ||
6401 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006402 !strcmp(child->name, "anyxml") ||
6403 !strcmp(child->name, "rpc") ||
6404 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006405 lyxml_unlink_elem(ctx, child, 2);
6406 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006407
Radek Krejci1d82ef62015-08-07 14:44:40 +02006408 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006409 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01006410 lyxml_unlink_elem(ctx, child, 2);
6411 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006412
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006413 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006414 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006415 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006416 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006417 goto error;
6418 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006419 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
6420 goto error;
6421 }
Radek Krejcic071c542016-01-27 14:57:51 +01006422 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006423 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006424 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006425 goto error;
6426 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006427 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006428 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006429 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006430 goto error;
6431 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006432 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
6433 goto error;
6434 }
Radek Krejcic071c542016-01-27 14:57:51 +01006435 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006436 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006437 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006438 goto error;
6439 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006440 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006441 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006442 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006443 goto error;
6444 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006445 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_ORGANIZATION, 0, unres)) {
6446 goto error;
6447 }
Radek Krejcic071c542016-01-27 14:57:51 +01006448 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006449 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006450 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006451 goto error;
6452 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006453 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006454 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006455 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006456 goto error;
6457 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006458 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_CONTACT, 0, unres)) {
6459 goto error;
6460 }
Radek Krejcic071c542016-01-27 14:57:51 +01006461 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006462 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006463 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006464 goto error;
6465 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006466 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006467 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006468 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006469 goto error;
6470 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006471 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02006472 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006473 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006474 goto error;
6475 }
Radek Krejcic071c542016-01-27 14:57:51 +01006476 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006477 if (!strcmp(value, "1")) {
6478 if (submodule) {
6479 if (module->version > 1) {
6480 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6481 goto error;
6482 }
6483 } else {
6484 module->version = 1;
6485 }
6486 } else {
6487 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006488 if (module->version < 2) {
Michal Vasko88de3e42016-06-29 11:05:32 +02006489 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6490 goto error;
6491 }
6492 } else {
6493 module->version = 2;
6494 }
6495 }
6496
Radek Krejci95f22ae2017-01-20 14:25:53 +01006497 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_VERSION, 0, unres)) {
6498 goto error;
6499 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006500 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006501
Radek Krejci1d82ef62015-08-07 14:44:40 +02006502 } else if (!strcmp(child->name, "extension")) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09006503 c_ext++;
Radek Krejci5166a892015-07-02 16:44:24 +02006504
Radek Krejcia1a6b762016-11-14 09:53:38 +09006505 } else if (!strcmp(child->name, "deviation")) {
6506 c_dev++;
6507
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006508 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01006509 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006510 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006511 }
6512 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006513
Radek Krejcic071c542016-01-27 14:57:51 +01006514 /* check for mandatory statements */
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006515 if (submodule) {
6516 if (!submodule->prefix) {
6517 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
6518 goto error;
6519 }
6520 if (!version_flag) {
6521 /* check version compatibility with the main module */
6522 if (module->version > 1) {
6523 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6524 goto error;
6525 }
6526 }
6527 } else {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006528 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006529 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006530 goto error;
6531 }
6532 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006533 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006534 goto error;
6535 }
6536 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02006537
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006538 /* allocate arrays for elements with cardinality of 0..n */
6539 if (c_imp) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006540 trg->imp = calloc(c_imp, sizeof *trg->imp);
Radek Krejcic071c542016-01-27 14:57:51 +01006541 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01006542 LOGMEM;
6543 goto error;
6544 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006545 }
6546 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006547 trg->rev = calloc(c_rev, sizeof *trg->rev);
6548 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01006549 LOGMEM;
6550 goto error;
6551 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006552 }
6553 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01006554 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
6555 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01006556 LOGMEM;
6557 goto error;
6558 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006559 }
6560 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01006561 trg->ident = calloc(c_ident, sizeof *trg->ident);
6562 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01006563 LOGMEM;
6564 goto error;
6565 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006566 }
6567 if (c_inc) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006568 trg->inc = calloc(c_inc, sizeof *trg->inc);
Radek Krejcic071c542016-01-27 14:57:51 +01006569 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01006570 LOGMEM;
6571 goto error;
6572 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006573 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006574 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01006575 trg->augment = calloc(c_aug, sizeof *trg->augment);
6576 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01006577 LOGMEM;
6578 goto error;
6579 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006580 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006581 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01006582 trg->features = calloc(c_ftrs, sizeof *trg->features);
6583 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01006584 LOGMEM;
6585 goto error;
6586 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006587 }
Radek Krejcieb00f512015-07-01 16:44:58 +02006588 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006589 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
6590 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01006591 LOGMEM;
6592 goto error;
6593 }
Radek Krejcieb00f512015-07-01 16:44:58 +02006594 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09006595 if (c_ext) {
6596 trg->extensions = calloc(c_ext, sizeof *trg->extensions);
6597 if (!trg->extensions) {
6598 LOGMEM;
6599 goto error;
6600 }
6601 }
Radek Krejcie534c132016-11-23 13:32:31 +01006602 if (c_extinst) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006603 /* some extensions may be already present from the substatements */
6604 reallocated = realloc(trg->ext, (c_extinst + trg->ext_size) * sizeof *trg->ext);
6605 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01006606 LOGMEM;
6607 goto error;
6608 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006609 trg->ext = reallocated;
6610
6611 /* init memory */
6612 memset(&trg->ext[trg->ext_size], 0, c_extinst * sizeof *trg->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006613 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006614
Michal Vasko2f7925f2015-10-21 15:06:56 +02006615 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
6616 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02006617 if (!strcmp(child->name, "import")) {
Radek Krejcie534c132016-11-23 13:32:31 +01006618 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size], unres);
Radek Krejcic071c542016-01-27 14:57:51 +01006619 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006620 if (r) {
6621 goto error;
6622 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006623
Radek Krejci1d82ef62015-08-07 14:44:40 +02006624 } else if (!strcmp(child->name, "include")) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006625 r = fill_yin_include(trg, submodule, child, &trg->inc[trg->inc_size], unres);
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006626 trg->inc_size++;
6627 if (r) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006628 goto error;
6629 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006630
Radek Krejci1d82ef62015-08-07 14:44:40 +02006631 } else if (!strcmp(child->name, "revision")) {
6632 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01006633 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006634 goto error;
6635 }
Radek Krejcic071c542016-01-27 14:57:51 +01006636 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006637 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01006638 for (i = 0; i < trg->rev_size; i++) {
6639 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006640 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
6641 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006642 }
6643 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006644
Radek Krejci95f22ae2017-01-20 14:25:53 +01006645 LY_TREE_FOR_SAFE(child->child, next2, child2) {
6646 if (!child2->ns) {
6647 /* garbage */
6648 continue;
6649 } else if (strcmp(child2->ns->value, LY_NSYIN)) {
6650 /* possible extension instance */
6651 if (read_yin_subnode_ext(trg, &trg->rev[trg->rev_size], LYEXT_PAR_REVISION,
6652 child2, LYEXT_SUBSTMT_SELF, 0, unres)) {
6653 goto error;
6654 }
6655 } else if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006656 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006657 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006658 goto error;
6659 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006660 if (read_yin_subnode_ext(trg, &trg->rev[trg->rev_size], LYEXT_PAR_REVISION,
6661 child2, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
6662 goto error;
6663 }
Radek Krejcic071c542016-01-27 14:57:51 +01006664 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
6665 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006666 goto error;
6667 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006668 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006669 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006670 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006671 goto error;
6672 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006673 if (read_yin_subnode_ext(trg, &trg->rev[trg->rev_size], LYEXT_PAR_REVISION,
6674 child2, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
6675 goto error;
6676 }
Radek Krejcic071c542016-01-27 14:57:51 +01006677 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
6678 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006679 goto error;
6680 }
6681 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01006682 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006683 goto error;
6684 }
6685 }
Radek Krejcic071c542016-01-27 14:57:51 +01006686 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006687
Radek Krejci1d82ef62015-08-07 14:44:40 +02006688 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006689 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
6690 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006691 if (r) {
6692 goto error;
6693 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006694
Radek Krejci1d82ef62015-08-07 14:44:40 +02006695 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006696 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
6697 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006698 if (r) {
6699 goto error;
6700 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006701
Radek Krejci1d82ef62015-08-07 14:44:40 +02006702 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006703 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
6704 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006705 if (r) {
6706 goto error;
6707 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006708
Radek Krejcia1a6b762016-11-14 09:53:38 +09006709 } else if (!strcmp(child->name, "extension")) {
Radek Krejcie534c132016-11-23 13:32:31 +01006710 r = fill_yin_extension(trg, child, &trg->extensions[trg->extensions_size], unres);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006711 trg->extensions_size++;
6712 if (r) {
6713 goto error;
6714 }
6715
Radek Krejci1d82ef62015-08-07 14:44:40 +02006716 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006717 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
6718 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02006719 if (r) {
6720 goto error;
6721 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006722 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006723 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006724
Radek Krejcie534c132016-11-23 13:32:31 +01006725 /* process extension instances */
6726 LY_TREE_FOR_SAFE(exts.child, next, child) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006727 r = lyp_yin_fill_ext(trg, LYEXT_PAR_MODULE, 0, 0, trg, child, &trg->ext, trg->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01006728 trg->ext_size++;
6729 if (r) {
6730 goto error;
6731 }
6732 }
6733
Radek Krejcif5be10f2015-06-16 13:29:36 +02006734 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01006735 * refer to them. Submodule's data nodes are stored in the
6736 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006737 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006738 LY_TREE_FOR_SAFE(grps.child, next, child) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006739 node = read_yin_grouping(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006740 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006741 goto error;
6742 }
Radek Krejci74705112015-06-05 10:25:44 +02006743
Michal Vasko345da0a2015-12-02 10:35:55 +01006744 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006745 }
Radek Krejci74705112015-06-05 10:25:44 +02006746
Radek Krejcif5be10f2015-06-16 13:29:36 +02006747 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006748 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02006749
Radek Krejci1d82ef62015-08-07 14:44:40 +02006750 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006751 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006752 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006753 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006754 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006755 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006756 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006757 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006758 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006759 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006760 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02006761 node = read_yin_uses(trg, NULL, child, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006762 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02006763 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 1, unres);
6764 } else if (!strcmp(child->name, "anydata")) {
6765 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006766 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006767 node = read_yin_rpc_action(trg, NULL, child, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006768 } else if (!strcmp(child->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006769 node = read_yin_notif(trg, NULL, child, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006770 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006771 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006772 goto error;
6773 }
Radek Krejci25d782a2015-05-22 15:03:23 +02006774
Michal Vasko345da0a2015-12-02 10:35:55 +01006775 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006776 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006777
Michal Vasko2f7925f2015-10-21 15:06:56 +02006778 /* ... and finally augments (last, so we can augment our data, for instance) */
6779 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01006780 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
6781 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02006782
Michal Vasko2f7925f2015-10-21 15:06:56 +02006783 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02006784 goto error;
6785 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006786 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02006787 }
6788
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006789 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02006790
6791error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006792 /* cleanup */
6793 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006794 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006795 }
6796 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006797 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006798 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006799 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006800 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006801 }
Radek Krejcie534c132016-11-23 13:32:31 +01006802 while (exts.child) {
6803 lyxml_free(module->ctx, exts.child);
6804 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006805
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006806 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02006807}
6808
Michal Vasko0d343d12015-08-24 14:57:36 +02006809/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01006810struct lys_submodule *
6811yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02006812{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006813 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01006814 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006815 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02006816
Michal Vasko5a721fd2016-02-16 12:16:48 +01006817 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02006818
Radek Krejci722b0072016-02-01 17:09:45 +01006819 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006820 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01006821 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006822 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006823
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006824 /* check root element */
6825 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006826 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006827 goto error;
6828 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006829
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006830 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01006831 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006832 goto error;
6833 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006834
Michal Vasko5a721fd2016-02-16 12:16:48 +01006835 submodule = calloc(1, sizeof *submodule);
6836 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006837 LOGMEM;
6838 goto error;
6839 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006840
Michal Vasko5a721fd2016-02-16 12:16:48 +01006841 submodule->ctx = module->ctx;
6842 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
6843 submodule->type = 1;
6844 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02006845
Michal Vasko5a721fd2016-02-16 12:16:48 +01006846 LOGVRB("Reading submodule \"%s\".", submodule->name);
6847 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006848 goto error;
6849 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006850
Radek Krejci33fc4772017-01-26 16:00:35 +01006851 lyp_sort_revisions((struct lys_module *)submodule);
6852
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006853 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01006854 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02006855
Michal Vasko5a721fd2016-02-16 12:16:48 +01006856 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006857 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02006858
6859error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006860 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01006861 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01006862 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01006863
Michal Vasko5a721fd2016-02-16 12:16:48 +01006864 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01006865 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01006866 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01006867 }
6868
Michal Vasko5a721fd2016-02-16 12:16:48 +01006869 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01006870
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006871 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
6872 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006873 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006874 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02006875}
6876
Michal Vasko0d343d12015-08-24 14:57:36 +02006877/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02006878struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01006879yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02006880{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006881 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01006882 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006883 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006884 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02006885
Radek Krejcic071c542016-01-27 14:57:51 +01006886 unres = calloc(1, sizeof *unres);
6887 if (!unres) {
6888 LOGMEM;
6889 return NULL;
6890 }
6891
Radek Krejci722b0072016-02-01 17:09:45 +01006892 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006893 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01006894 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006895 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006896
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006897 /* check root element */
6898 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci9a909bd2016-10-24 15:45:51 +02006899 if (ly_strequal("submodule", yin->name, 0)) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01006900 LOGVAL(LYE_SUBMODULE, LY_VLOG_NONE, NULL);
6901 } else {
6902 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci9a909bd2016-10-24 15:45:51 +02006903 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006904 goto error;
6905 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006906
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006907 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01006908 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006909 goto error;
6910 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006911
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006912 module = calloc(1, sizeof *module);
6913 if (!module) {
6914 LOGMEM;
6915 goto error;
6916 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006917
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006918 module->ctx = ctx;
6919 module->name = lydict_insert(ctx, value, strlen(value));
6920 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02006921 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02006922
Michal Vasko9f258e42016-02-11 11:36:27 +01006923 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01006924 if (read_sub_module(module, NULL, yin, unres)) {
6925 goto error;
6926 }
6927
6928 /* resolve rest of unres items */
6929 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006930 goto error;
6931 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006932
Radek Krejci95f22ae2017-01-20 14:25:53 +01006933 lyp_sort_revisions(module);
Radek Krejcibf285832017-01-26 16:05:41 +01006934 lyp_rfn_apply_ext(module);
Radek Krejci95f22ae2017-01-20 14:25:53 +01006935
Radek Krejciff4874d2016-03-07 12:30:50 +01006936 if (revision) {
6937 /* check revision of the parsed model */
6938 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01006939 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
6940 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01006941 goto error;
6942 }
6943 }
6944
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006945 /* check correctness of includes */
6946 if (lyp_check_include_missing(module)) {
6947 goto error;
6948 }
6949
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006950 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01006951 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006952 }
Radek Krejci63a91a92015-07-29 13:31:04 +02006953
Radek Krejci27fe55e2016-09-13 17:13:35 +02006954 if (module->deviation_size && !module->implemented) {
6955 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
6956 /* deviations always causes target to be made implemented,
6957 * but augents and leafrefs not, so we have to apply them now */
6958 if (lys_set_implemented(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02006959 goto error;
6960 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006961 }
6962
Michal Vasko345da0a2015-12-02 10:35:55 +01006963 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01006964 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01006965 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006966 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006967
6968error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006969 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01006970 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01006971 unres_schema_free(module, &unres);
6972
6973 if (!module) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01006974 if (ly_vecode != LYVE_SUBMODULE) {
6975 LOGERR(ly_errno, "Module parsing failed.");
6976 }
Radek Krejcib8c07b82016-02-12 11:11:55 +01006977 return NULL;
6978 }
6979
6980 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006981
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006982 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01006983 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006984 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006985}