blob: 447218b406acf6c4ed67a818aed6afcefaddfd0e [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 */
Radek Krejci30bfcd22017-01-27 16:54:48 +01002158 parent = dev_target->parent;
Michal Vaskoff006c12016-02-17 11:15:19 +01002159 lys_node_unlink(dev_target);
Radek Krejci30bfcd22017-01-27 16:54:48 +01002160 if (parent && parent->nodetype == LYS_AUGMENT) {
2161 /* hack for augment, because when the original will be sometime reconnected back, we actually need
2162 * to reconnect it to both - the augment and its target (which is deduced from the deviations target
2163 * path), so we need to remember the augment as an addition */
2164 dev_target->parent = parent;
2165 }
Michal Vaskoff006c12016-02-17 11:15:19 +01002166 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02002167
Radek Krejcieb00f512015-07-01 16:44:58 +02002168 } else if (!strcmp(value, "add")) {
2169 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
2170 } else if (!strcmp(value, "replace")) {
2171 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
2172 } else if (!strcmp(value, "delete")) {
2173 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
2174 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002175 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002176 goto error;
2177 }
2178 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01002179 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002180
Michal Vaskoff006c12016-02-17 11:15:19 +01002181 /* store a shallow copy of the original node */
2182 if (!dev->orig_node) {
2183 memset(&tmp_unres, 0, sizeof tmp_unres);
Radek Krejci6ff885d2017-01-03 14:06:22 +01002184 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, &tmp_unres, 1);
Michal Vaskoff006c12016-02-17 11:15:19 +01002185 /* just to be safe */
2186 if (tmp_unres.count) {
2187 LOGINT;
2188 goto error;
2189 }
2190 }
2191
Radek Krejcieb00f512015-07-01 16:44:58 +02002192 /* process deviation properties */
Radek Krejcie534c132016-11-23 13:32:31 +01002193 LY_TREE_FOR_SAFE(develem->child, next2, child) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002194 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002195 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002196 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002197 continue;
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002198 } else if (strcmp(child->ns->value, LY_NSYIN)) {
2199 /* extensions */
2200 c_ext++;
2201 } else if (d->mod == LY_DEVIATE_NO) {
2202 /* no YIN substatement expected in this case */
2203 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2204 goto error;
2205 } else if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002206 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002207 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002208 goto error;
2209 }
2210
2211 /* for we deviate from RFC 6020 and allow config property even it is/is not
2212 * specified in the target explicitly since config property inherits. So we expect
2213 * that config is specified in every node. But for delete, we check that the value
2214 * is the same as here in deviation
2215 */
2216 GETVAL(value, child, "value");
2217 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002218 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02002219 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002220 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02002221 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002222 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002223 goto error;
2224 }
2225
2226 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002227 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002228 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002229 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002230 } else { /* add and replace are the same in this case */
2231 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01002232 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002233
2234 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01002235 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02002236 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002237
2238 if (read_yin_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
2239 goto error;
2240 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002241 } else if (!strcmp(child->name, "default")) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002242 if (read_yin_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_DEFAULT, c_dflt, unres)) {
2243 goto error;
2244 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002245 c_dflt++;
2246
2247 /* check target node type */
2248 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
2249 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2250 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
2251 goto error;
2252 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
2253 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2254 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
2255 goto error;
2256 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
2257 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2258 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002259 goto error;
2260 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002261
Radek Krejcid5a5c282016-08-15 15:38:08 +02002262 /* skip lyxml_free() at the end of the loop, this node will be processed later */
2263 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02002264
Radek Krejcieb00f512015-07-01 16:44:58 +02002265 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002266 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002267 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002268 goto error;
2269 }
2270
2271 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002272 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002273 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2274 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002275 goto error;
2276 }
2277
2278 GETVAL(value, child, "value");
2279 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002280 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002281 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002282 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002283 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002284 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002285 goto error;
2286 }
2287
2288 if (d->mod == LY_DEVIATE_ADD) {
2289 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01002290 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002291 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2292 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002293 goto error;
2294 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002295
Radek Krejci841ec082016-04-05 13:05:17 +02002296 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02002297 if (d->flags & LYS_MAND_TRUE) {
2298 if (dev_target->nodetype == LYS_CHOICE) {
2299 if (((struct lys_node_choice *)(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 choice with the \"default\" statement.");
2303 goto error;
2304 }
2305 } else if (dev_target->nodetype == LYS_LEAF) {
2306 if (((struct lys_node_leaf *)(dev_target))->dflt) {
2307 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2308 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2309 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
2310 goto error;
2311 }
2312 }
Radek Krejci841ec082016-04-05 13:05:17 +02002313 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002314
Michal Vasko21be1b32016-03-07 12:31:34 +01002315 dev_target->flags |= d->flags & LYS_MAND_MASK;
2316 } else if (d->mod == LY_DEVIATE_RPL) {
2317 /* check that there was a value before */
2318 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002319 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2320 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002321 goto error;
2322 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002323
Michal Vasko21be1b32016-03-07 12:31:34 +01002324 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01002325 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01002326 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002327 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002328 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002329 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002330 }
Radek Krejcie00d2312016-08-12 15:27:49 +02002331
2332 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2333 for (parent = dev_target->parent;
2334 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2335 parent = parent->parent) {
2336 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2337 /* stop also on presence containers */
2338 break;
2339 }
2340 }
2341 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2342 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2343 if (lyp_check_mandatory_choice(parent)) {
2344 goto error;
2345 }
2346 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002347
2348 if (read_yin_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
2349 goto error;
2350 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002351 } else if (!strcmp(child->name, "min-elements")) {
2352 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002353 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002354 goto error;
2355 }
2356 f_min = 1;
2357
Michal Vasko60f4b452016-02-12 11:02:55 +01002358 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002359 goto error;
2360 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002361 if (read_yin_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MIN, 0, unres)) {
2362 goto error;
2363 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002364 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01002365 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002366 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002367 goto error;
2368 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01002369 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02002370
Michal Vasko60f4b452016-02-12 11:02:55 +01002371 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002372 goto error;
2373 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002374 if (read_yin_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_MAX, 0, unres)) {
2375 goto error;
2376 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002377 } else if (!strcmp(child->name, "must")) {
2378 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002379 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002380 continue;
2381 } else if (!strcmp(child->name, "type")) {
2382 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002383 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002384 goto error;
2385 }
2386
Michal Vaskof7e57d52016-03-07 11:31:09 +01002387 /* add, del type is forbidden */
2388 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002389 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002390 goto error;
2391 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002392 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002393 goto error;
2394 }
2395
Radek Krejcieb00f512015-07-01 16:44:58 +02002396 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002397 if (dev_target->nodetype == LYS_LEAF) {
2398 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002399 if (((struct lys_node_leaf *)dev_target)->dflt) {
2400 ly_set_add(dflt_check, dev_target, 0);
2401 }
Michal Vasko60f4b452016-02-12 11:02:55 +01002402 } else if (dev_target->nodetype == LYS_LEAFLIST) {
2403 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02002404 if (((struct lys_node_leaflist *)dev_target)->dflt) {
2405 ly_set_add(dflt_check, dev_target, 0);
2406 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002407 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002408 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2409 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002410 goto error;
2411 }
2412
Radek Krejcieb00f512015-07-01 16:44:58 +02002413 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002414 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01002415 /* HACK for unres */
2416 t->der = (struct lys_tpdf *)child;
Michal Vasko3767fb22016-07-21 12:10:57 +02002417 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002418 goto error;
2419 }
2420 d->type = t;
2421 } else if (!strcmp(child->name, "unique")) {
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002422 if (read_yin_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_UNIQUE, c_uniq, unres)) {
2423 goto error;
2424 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002425 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002426 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02002427 continue;
2428 } else if (!strcmp(child->name, "units")) {
2429 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002430 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002431 goto error;
2432 }
2433
2434 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002435 if (dev_target->nodetype == LYS_LEAFLIST) {
2436 stritem = &((struct lys_node_leaflist *)dev_target)->units;
2437 } else if (dev_target->nodetype == LYS_LEAF) {
2438 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02002439 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002440 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2441 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002442 goto error;
2443 }
2444
2445 /* get units value */
2446 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002447 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02002448
2449 /* apply to target */
2450 if (d->mod == LY_DEVIATE_ADD) {
2451 /* check that there is no current value */
2452 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002453 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2454 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002455 goto error;
2456 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002457
Michal Vasko21be1b32016-03-07 12:31:34 +01002458 *stritem = lydict_insert(ctx, value, 0);
2459 } else if (d->mod == LY_DEVIATE_RPL) {
2460 /* check that there was a value before */
2461 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002462 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2463 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01002464 goto error;
2465 }
2466
2467 lydict_remove(ctx, *stritem);
2468 *stritem = lydict_insert(ctx, value, 0);
2469 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002470 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002471 if (!ly_strequal(*stritem, d->units, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002472 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2473 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002474 goto error;
2475 }
2476 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002477 lydict_remove(ctx, *stritem);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002478 (*stritem) = NULL;
2479 }
2480
2481 if (read_yin_subnode_ext(module, d, LYEXT_PAR_DEVIATE, child, LYEXT_SUBSTMT_UNITS, 0, unres)) {
2482 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002483 }
2484 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002485 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002486 goto error;
2487 }
2488
Michal Vasko88c29542015-11-27 14:57:53 +01002489 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002490 }
2491
2492 if (c_must) {
2493 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002494 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002495 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002496 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2497 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002498 break;
Radek Krejci76512572015-08-04 09:47:08 +02002499 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002500 trg_must = &((struct lys_node_container *)dev_target)->must;
2501 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002502 break;
Radek Krejci76512572015-08-04 09:47:08 +02002503 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002504 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2505 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002506 break;
Radek Krejci76512572015-08-04 09:47:08 +02002507 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002508 trg_must = &((struct lys_node_list *)dev_target)->must;
2509 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002510 break;
Radek Krejci76512572015-08-04 09:47:08 +02002511 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002512 case LYS_ANYDATA:
2513 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2514 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002515 break;
2516 default:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002517 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2518 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002519 goto error;
2520 }
2521
Michal Vaskoe3886bb2017-01-02 11:33:28 +01002522 dev_target->flags &= ~LYS_XPATH_DEP;
Michal Vasko508a50d2016-09-07 14:50:33 +02002523
Radek Krejcieb00f512015-07-01 16:44:58 +02002524 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002525 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002526 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002527 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002528 } else if (d->mod == LY_DEVIATE_ADD) {
2529 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002530 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002531 if (!d->must) {
2532 LOGMEM;
2533 goto error;
2534 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002535 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02002536 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002537 d->must_size = c_must;
2538 } else { /* LY_DEVIATE_DEL */
2539 d->must = calloc(c_must, sizeof *d->must);
2540 }
Michal Vasko253035f2015-12-17 16:58:13 +01002541 if (!d->must) {
2542 LOGMEM;
2543 goto error;
2544 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002545 }
2546 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002547 /* replace unique is forbidden */
2548 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002549 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002550 goto error;
2551 }
2552
Radek Krejcieb00f512015-07-01 16:44:58 +02002553 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002554 if (dev_target->nodetype != LYS_LIST) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002555 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2556 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002557 goto error;
2558 }
2559
Michal Vasko60f4b452016-02-12 11:02:55 +01002560 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002561 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002562 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002563 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02002564 list->unique = d->unique;
2565 d->unique = &list->unique[list->unique_size];
2566 d->unique_size = c_uniq;
2567 } else { /* LY_DEVIATE_DEL */
2568 d->unique = calloc(c_uniq, sizeof *d->unique);
2569 }
Michal Vasko253035f2015-12-17 16:58:13 +01002570 if (!d->unique) {
2571 LOGMEM;
2572 goto error;
2573 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002574 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002575 if (c_dflt) {
2576 if (d->mod == LY_DEVIATE_ADD) {
2577 /* check that there is no current value */
2578 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
2579 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
2580 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2581 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
2582 goto error;
2583 }
2584
2585 /* check collision with mandatory/min-elements */
2586 if ((dev_target->flags & LYS_MAND_TRUE) ||
2587 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
2588 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2589 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2590 "Adding the \"default\" statement is forbidden on %s statement.",
2591 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2592 goto error;
2593 }
2594 } else if (d->mod == LY_DEVIATE_RPL) {
2595 /* check that there was a value before */
2596 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2597 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
2598 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2599 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
2600 goto error;
2601 }
2602 }
2603
2604 if (dev_target->nodetype == LYS_LEAFLIST) {
2605 /* reallocate default list in the target */
2606 llist = (struct lys_node_leaflist *)dev_target;
2607 if (d->mod == LY_DEVIATE_ADD) {
2608 /* reallocate (enlarge) the unique array of the target */
2609 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
2610 } else if (d->mod == LY_DEVIATE_RPL) {
2611 /* reallocate (replace) the unique array of the target */
2612 for (i = 0; i < llist->dflt_size; i++) {
2613 lydict_remove(llist->module->ctx, llist->dflt[i]);
2614 }
2615 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2616 llist->dflt_size = 0;
2617 }
2618 }
2619 d->dflt = calloc(c_dflt, sizeof *d->dflt);
2620 if (!d->dflt) {
2621 LOGMEM;
2622 goto error;
2623 }
2624 }
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002625 if (c_ext) {
2626 /* some extensions may be already present from the substatements */
2627 reallocated = realloc(d->ext, (c_ext + d->ext_size) * sizeof *d->ext);
2628 if (!reallocated) {
2629 LOGMEM;
2630 goto error;
2631 }
2632 d->ext = reallocated;
2633
2634 /* init memory */
2635 memset(&d->ext[d->ext_size], 0, c_ext * sizeof *d->ext);
2636 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002637
2638 /* process deviation properties with 0..n cardinality */
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002639 LY_TREE_FOR_SAFE(develem->child, next2, child) {
2640 if (strcmp(child->ns->value, LY_NSYIN)) {
2641 /* extension */
2642 if (lyp_yin_fill_ext(d, LYEXT_PAR_DEVIATE, 0, 0, module, child, &d->ext, d->ext_size, unres)) {
2643 goto error;
2644 }
2645 d->ext_size++;
2646 } else if (!strcmp(child->name, "must")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002647 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcifccd1442017-01-16 10:26:57 +01002648 if (fill_yin_must(module, child, &d->must[d->must_size], unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002649 goto error;
2650 }
2651
2652 /* find must to delete, we are ok with just matching conditions */
2653 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002654 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002655 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002656 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02002657 /* ... and maintain the array */
2658 (*trg_must_size)--;
2659 if (i != *trg_must_size) {
2660 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2661 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2662 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2663 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2664 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2665 }
2666 if (!(*trg_must_size)) {
2667 free(*trg_must);
2668 *trg_must = NULL;
2669 } else {
2670 (*trg_must)[*trg_must_size].expr = NULL;
2671 (*trg_must)[*trg_must_size].dsc = NULL;
2672 (*trg_must)[*trg_must_size].ref = NULL;
2673 (*trg_must)[*trg_must_size].eapptag = NULL;
2674 (*trg_must)[*trg_must_size].emsg = NULL;
2675 }
2676
2677 i = -1; /* set match flag */
2678 break;
2679 }
2680 }
2681 d->must_size++;
2682 if (i != -1) {
2683 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002684 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002685 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01002686 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002687 goto error;
2688 }
2689 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002690 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
Radek Krejcifccd1442017-01-16 10:26:57 +01002691 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]), unres)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002692 goto error;
2693 }
2694 (*trg_must_size)++;
2695 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002696
2697 /* check XPath dependencies again */
Michal Vaskoe8734262016-09-29 14:12:06 +02002698 if (*trg_must_size && unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL)) {
Michal Vasko508a50d2016-09-07 14:50:33 +02002699 goto error;
2700 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002701 } else if (!strcmp(child->name, "unique")) {
2702 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002703 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002704 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002705 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002706 goto error;
2707 }
2708
2709 /* find unique structures to delete */
2710 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002711 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002712 continue;
2713 }
2714
Radek Krejci581ce772015-11-10 17:22:40 +01002715 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002716 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002717 break;
2718 }
2719 }
2720
Radek Krejci581ce772015-11-10 17:22:40 +01002721 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002722 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002723 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002724 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002725 }
2726 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002727 /* ... and maintain the array */
2728 list->unique_size--;
2729 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002730 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2731 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002732 }
2733
2734 if (!list->unique_size) {
2735 free(list->unique);
2736 list->unique = NULL;
2737 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002738 list->unique[list->unique_size].expr_size = 0;
2739 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002740 }
2741
2742 i = -1; /* set match flag */
2743 break;
2744 }
2745 }
2746
2747 d->unique_size++;
2748 if (i != -1) {
2749 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002750 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2751 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002752 goto error;
2753 }
2754 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002755 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002756 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002757 list->unique_size++;
2758 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002759 goto error;
2760 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002761 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002762 } else if (!strcmp(child->name, "default")) {
2763 GETVAL(value, child, "value");
2764 u = strlen(value);
2765 d->dflt[d->dflt_size++] = lydict_insert(module->ctx, value, u);
2766
2767 if (dev_target->nodetype == LYS_CHOICE) {
2768 choice = (struct lys_node_choice *)dev_target;
2769 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2770 if (rc || !node) {
2771 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2772 goto error;
2773 }
2774 if (d->mod == LY_DEVIATE_DEL) {
2775 if (!choice->dflt || (choice->dflt != node)) {
2776 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2777 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2778 goto error;
2779 }
2780 } else { /* add or replace */
2781 choice->dflt = node;
2782 if (!choice->dflt) {
2783 /* default branch not found */
2784 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2785 goto error;
2786 }
2787 }
2788 } else if (dev_target->nodetype == LYS_LEAF) {
2789 leaf = (struct lys_node_leaf *)dev_target;
2790 if (d->mod == LY_DEVIATE_DEL) {
2791 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
2792 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2793 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2794 goto error;
2795 }
2796 /* remove value */
2797 lydict_remove(ctx, leaf->dflt);
2798 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01002799 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002800 } else { /* add (already checked) and replace */
2801 /* remove value */
2802 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01002803 leaf->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002804
2805 /* set new value */
2806 leaf->dflt = lydict_insert(ctx, value, u);
2807
Radek Krejcibd117f02016-11-04 16:28:08 +01002808 /* remember to check it later (it may not fit now, because the type can be deviated too) */
Radek Krejcid5a5c282016-08-15 15:38:08 +02002809 ly_set_add(dflt_check, dev_target, 0);
2810 }
2811 } else { /* LYS_LEAFLIST */
2812 llist = (struct lys_node_leaflist *)dev_target;
2813 if (d->mod == LY_DEVIATE_DEL) {
2814 /* find and remove the value in target list */
2815 for (i = 0; i < llist->dflt_size; i++) {
2816 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
2817 /* match, remove the value */
2818 lydict_remove(llist->module->ctx, llist->dflt[i]);
2819 llist->dflt[i] = NULL;
2820 break;
2821 }
2822 }
2823 if (i == llist->dflt_size) {
2824 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2825 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
2826 goto error;
2827 }
2828 } else {
2829 /* add or replace, anyway we place items into the deviate's list
2830 which propagates to the target */
2831 /* we just want to check that the value isn't already in the list */
2832 for (i = 0; i < llist->dflt_size; i++) {
2833 if (ly_strequal(llist->dflt[i], value, 1)) {
2834 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2835 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2836 goto error;
2837 }
2838 }
2839 /* store it in target node */
2840 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, u);
2841
2842 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2843 ly_set_add(dflt_check, dev_target, 0);
Radek Krejci3c4b0ea2017-01-24 16:00:47 +01002844 llist->flags &= ~LYS_DFLTJSON;
Radek Krejcid5a5c282016-08-15 15:38:08 +02002845 }
2846 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002847 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002848 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002849
2850 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
2851 /* consolidate the final list in the target after removing items from it */
2852 llist = (struct lys_node_leaflist *)dev_target;
2853 for (i = j = 0; j < llist->dflt_size; j++) {
2854 llist->dflt[i] = llist->dflt[j];
2855 if (llist->dflt[i]) {
2856 i++;
2857 }
2858 }
2859 llist->dflt_size = i + 1;
2860 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002861 }
2862
Michal Vasko43a1feb2016-03-07 12:03:02 +01002863 /* now check whether default value, if any, matches the type */
Pavol Vican85991ec2016-08-16 14:58:12 +02002864 for (u = 0; u < dflt_check->number; ++u) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002865 value = NULL;
2866 rc = EXIT_SUCCESS;
2867 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2868 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
Radek Krejci51673202016-11-01 17:00:32 +01002869 value = leaf->dflt;
2870 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002871 } else { /* LYS_LEAFLIST */
2872 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2873 for (j = 0; j < llist->dflt_size; j++) {
Radek Krejci51673202016-11-01 17:00:32 +01002874 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2875 (struct lys_node *)(&llist->dflt[j]));
Radek Krejcid5a5c282016-08-15 15:38:08 +02002876 if (rc == -1) {
Radek Krejci51673202016-11-01 17:00:32 +01002877 value = llist->dflt[j];
Radek Krejcid5a5c282016-08-15 15:38:08 +02002878 break;
2879 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002880 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002881
2882 }
2883 if (rc == -1) {
2884 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2885 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2886 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2887 dev->target_name);
2888 goto error;
Michal Vasko43a1feb2016-03-07 12:03:02 +01002889 }
2890 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002891
Radek Krejci27fe55e2016-09-13 17:13:35 +02002892 /* mark all the affected modules as deviated and implemented */
2893 for(parent = dev_target; parent; parent = lys_parent(parent)) {
2894 mod = lys_node_module(parent);
2895 if (module != mod) {
2896 mod->deviated = 1;
2897 lys_set_implemented(mod);
2898 }
2899 }
2900
Radek Krejcid5a5c282016-08-15 15:38:08 +02002901 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002902 return EXIT_SUCCESS;
2903
2904error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002905 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002906 return EXIT_FAILURE;
2907}
2908
Michal Vasko0d343d12015-08-24 14:57:36 +02002909/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002910static int
Radek Krejcib8048692015-08-05 13:36:34 +02002911fill_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 +02002912 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02002913{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002914 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01002915 struct lyxml_elem *sub, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002916 struct lys_node *node;
Radek Krejcie534c132016-11-23 13:32:31 +01002917 int ret, c_ftrs = 0, c_ext = 0;
Radek Krejci30701b42017-01-23 16:41:38 +01002918 void *reallocated;
Radek Krejci106efc02015-06-10 14:36:27 +02002919
Michal Vasko591e0b22015-08-13 13:53:43 +02002920 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002921 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002922 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02002923 if (!aug->target_name) {
2924 goto error;
2925 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002926 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02002927
Radek Krejci07d0fb92017-01-13 14:11:05 +01002928 if (read_yin_common(module, NULL, aug, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002929 goto error;
2930 }
2931
Radek Krejcie534c132016-11-23 13:32:31 +01002932 LY_TREE_FOR_SAFE(yin->child, next, sub) {
2933 if (strcmp(sub->ns->value, LY_NSYIN)) {
2934 /* extension */
2935 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02002936 continue;
Radek Krejci30701b42017-01-23 16:41:38 +01002937 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejcie534c132016-11-23 13:32:31 +01002938 c_ftrs++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002939 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01002940 } else if (!strcmp(sub->name, "when")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002941 if (aug->when) {
Radek Krejcie534c132016-11-23 13:32:31 +01002942 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002943 goto error;
2944 }
2945
Radek Krejci5323b492017-01-16 15:40:11 +01002946 aug->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002947 if (!aug->when) {
Radek Krejcie534c132016-11-23 13:32:31 +01002948 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002949 goto error;
2950 }
Radek Krejcie534c132016-11-23 13:32:31 +01002951 lyxml_free(module->ctx, sub);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002952 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002953
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002954 /* check allowed data sub-statements */
Radek Krejcie534c132016-11-23 13:32:31 +01002955 } else if (!strcmp(sub->name, "container")) {
2956 node = read_yin_container(module, (struct lys_node *)aug, sub, 1, unres);
2957 } else if (!strcmp(sub->name, "leaf-list")) {
2958 node = read_yin_leaflist(module, (struct lys_node *)aug, sub, 1, unres);
2959 } else if (!strcmp(sub->name, "leaf")) {
2960 node = read_yin_leaf(module, (struct lys_node *)aug, sub, 1, unres);
2961 } else if (!strcmp(sub->name, "list")) {
2962 node = read_yin_list(module, (struct lys_node *)aug, sub, 1, unres);
2963 } else if (!strcmp(sub->name, "uses")) {
2964 node = read_yin_uses(module, (struct lys_node *)aug, sub, unres);
2965 } else if (!strcmp(sub->name, "choice")) {
2966 node = read_yin_choice(module, (struct lys_node *)aug, sub, 1, unres);
2967 } else if (!strcmp(sub->name, "case")) {
2968 node = read_yin_case(module, (struct lys_node *)aug, sub, 1, unres);
2969 } else if (!strcmp(sub->name, "anyxml")) {
2970 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYXML, 1, unres);
2971 } else if (!strcmp(sub->name, "anydata")) {
2972 node = read_yin_anydata(module, (struct lys_node *)aug, sub, LYS_ANYDATA, 1, unres);
2973 } else if (!strcmp(sub->name, "action")) {
2974 node = read_yin_rpc_action(module, (struct lys_node *)aug, sub, unres);
2975 } else if (!strcmp(sub->name, "notification")) {
2976 node = read_yin_notif(module, (struct lys_node *)aug, sub, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002977 } else {
Radek Krejcie534c132016-11-23 13:32:31 +01002978 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002979 goto error;
2980 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002981
Radek Krejci1d82ef62015-08-07 14:44:40 +02002982 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002983 goto error;
2984 }
2985
Radek Krejci1d82ef62015-08-07 14:44:40 +02002986 node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01002987 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002988 }
2989
Radek Krejcie534c132016-11-23 13:32:31 +01002990 if (c_ftrs) {
2991 aug->iffeature = calloc(c_ftrs, sizeof *aug->iffeature);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002992 if (!aug->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002993 LOGMEM;
2994 goto error;
2995 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002996 }
Radek Krejcie534c132016-11-23 13:32:31 +01002997 if (c_ext) {
Radek Krejci30701b42017-01-23 16:41:38 +01002998 /* some extensions may be already present from the substatements */
2999 reallocated = realloc(aug->ext, (c_ext + aug->ext_size) * sizeof *aug->ext);
3000 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003001 LOGMEM;
3002 goto error;
3003 }
Radek Krejci30701b42017-01-23 16:41:38 +01003004 aug->ext = reallocated;
3005
3006 /* init memory */
3007 memset(&aug->ext[aug->ext_size], 0, c_ext * sizeof *aug->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003008 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003009
Radek Krejcie534c132016-11-23 13:32:31 +01003010 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3011 if (strcmp(sub->ns->value, LY_NSYIN)) {
3012 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003013 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 +01003014 aug->ext_size++;
3015 if (ret) {
3016 goto error;
3017 }
3018 } else if (!strcmp(sub->name, "if-feature")) {
3019 ret = fill_yin_iffeature((struct lys_node *)aug, 0, sub, &aug->iffeature[aug->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003020 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003021 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003022 goto error;
3023 }
Radek Krejcie534c132016-11-23 13:32:31 +01003024 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003025 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003026 }
3027
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003028 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02003029 * connected to the tree and adjusted (if possible right now).
Radek Krejci27fe55e2016-09-13 17:13:35 +02003030 * However, if this is augment in a uses (parent is NULL), it gets resolved
Michal Vasko49291b32015-08-06 09:49:41 +02003031 * when the uses does and cannot be resolved now for sure
3032 * (the grouping was not yet copied into uses).
3033 */
Radek Krejci27fe55e2016-09-13 17:13:35 +02003034 if (!parent) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003035 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02003036 goto error;
3037 }
Michal Vasko49291b32015-08-06 09:49:41 +02003038 }
Radek Krejci106efc02015-06-10 14:36:27 +02003039
Michal Vasko508a50d2016-09-07 14:50:33 +02003040 /* check XPath dependencies */
3041 if (aug->when && (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1)) {
3042 goto error;
3043 }
3044
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003045 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02003046
3047error:
3048
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003049 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02003050}
3051
Michal Vasko0d343d12015-08-24 14:57:36 +02003052/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003053static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02003054fill_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 +02003055{
Radek Krejci363bd4a2016-07-29 14:30:20 +02003056 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003057 struct lyxml_elem *sub, *next;
3058 const char *value;
3059 char *endptr;
3060 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01003061 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003062 int r;
3063 unsigned long int val;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003064 void *reallocated;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003065
Radek Krejci363bd4a2016-07-29 14:30:20 +02003066 assert(uses);
3067 module = uses->module; /* shorthand */
3068
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003069 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01003070 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02003071 if (!rfn->target_name) {
3072 goto error;
3073 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003074
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003075 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci411b1bf2017-01-23 16:40:05 +01003076 if (!sub->ns) {
3077 /* garbage */
3078 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01003079 /* extension */
3080 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02003081 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02003082
Radek Krejci411b1bf2017-01-23 16:40:05 +01003083 } else if (!strcmp(sub->name, "description")) {
3084 if (rfn->dsc) {
3085 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3086 goto error;
3087 }
3088
3089 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
3090 goto error;
3091 }
3092
3093 rfn->dsc = read_yin_subnode(module->ctx, sub, "text");
3094 if (!rfn->dsc) {
3095 goto error;
3096 }
3097 } else if (!strcmp(sub->name, "reference")) {
3098 if (rfn->ref) {
3099 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3100 goto error;
3101 }
3102
3103 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
3104 goto error;
3105 }
3106
3107 rfn->ref = read_yin_subnode(module->ctx, sub, "text");
3108 if (!rfn->ref) {
3109 goto error;
3110 }
3111 } else if (!strcmp(sub->name, "config")) {
3112 if (rfn->flags & LYS_CONFIG_MASK) {
3113 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3114 goto error;
3115 }
3116 GETVAL(value, sub, "value");
3117 if (!strcmp(value, "false")) {
3118 rfn->flags |= LYS_CONFIG_R;
3119 } else if (!strcmp(value, "true")) {
3120 rfn->flags |= LYS_CONFIG_W;
3121 } else {
3122 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3123 goto error;
3124 }
3125 rfn->flags |= LYS_CONFIG_SET;
3126
3127 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
3128 goto error;
3129 }
Radek Krejcie534c132016-11-23 13:32:31 +01003130 } else if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02003131 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02003132
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003133 /* check possibility of statements combination */
3134 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02003135 if (c_dflt) {
3136 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003137 if (module->version < 2) {
3138 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
3139 goto error;
3140 }
Radek Krejci200bf712016-08-16 17:11:04 +02003141 rfn->target_type &= LYS_LEAFLIST;
3142 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003143 if (module->version < 2) {
3144 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
3145 } else {
3146 /* YANG 1.1 */
3147 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
3148 }
Radek Krejci200bf712016-08-16 17:11:04 +02003149 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003150 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003151 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3152 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003153 goto error;
3154 }
3155 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003156 if (module->version < 2) {
3157 rfn->target_type = LYS_LEAF | LYS_CHOICE;
3158 } else {
3159 /* YANG 1.1 */
3160 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
3161 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003162 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003163
Radek Krejcifdc0d702017-01-23 15:58:38 +01003164 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_DEFAULT, c_dflt, unres)) {
3165 goto error;
3166 }
Radek Krejci200bf712016-08-16 17:11:04 +02003167 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003168 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003169 } else if (!strcmp(sub->name, "mandatory")) {
3170 /* leaf, choice or anyxml */
3171 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003172 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003173 goto error;
3174 }
3175 /* just checking the flags in leaf is not sufficient, we would allow
3176 * multiple mandatory statements with the "false" value
3177 */
3178 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003180 /* check possibility of statements combination */
3181 if (rfn->target_type) {
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 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003184 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3185 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003186 goto error;
3187 }
3188 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003189 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003190 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003191
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003192 GETVAL(value, sub, "value");
3193 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003194 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003195 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003196 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003197 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003198 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003199 goto error;
3200 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01003201 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
3202 goto error;
3203 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003204 } else if (!strcmp(sub->name, "min-elements")) {
3205 /* list or leaf-list */
3206 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003207 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003208 goto error;
3209 }
3210 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003211
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003212 /* check possibility of statements combination */
3213 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003214 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003215 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003216 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3217 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003218 goto error;
3219 }
3220 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003221 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003222 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003223
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003224 GETVAL(value, sub, "value");
3225 while (isspace(value[0])) {
3226 value++;
3227 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003228
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003229 /* convert it to uint32_t */
3230 errno = 0;
3231 endptr = NULL;
3232 val = strtoul(value, &endptr, 10);
3233 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003234 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003235 goto error;
3236 }
3237 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003238 rfn->flags |= LYS_RFN_MINSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003239
3240 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
3241 goto error;
3242 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003243 } else if (!strcmp(sub->name, "max-elements")) {
3244 /* list or leaf-list */
3245 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003246 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003247 goto error;
3248 }
3249 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003250
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003251 /* check possibility of statements combination */
3252 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003253 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003254 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003255 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3256 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003257 goto error;
3258 }
3259 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003260 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003261 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003262
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003263 GETVAL(value, sub, "value");
3264 while (isspace(value[0])) {
3265 value++;
3266 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003267
Radek Krejci0d7b2472016-02-12 11:11:03 +01003268 if (!strcmp(value, "unbounded")) {
3269 rfn->mod.list.max = 0;
3270 } else {
3271 /* convert it to uint32_t */
3272 errno = 0;
3273 endptr = NULL;
3274 val = strtoul(value, &endptr, 10);
3275 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003276 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003277 goto error;
3278 }
3279 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003280 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02003281 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejcifdc0d702017-01-23 15:58:38 +01003282
3283 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
3284 goto error;
3285 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003286 } else if (!strcmp(sub->name, "presence")) {
3287 /* container */
3288 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003289 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003290 goto error;
3291 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003292
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003293 /* check possibility of statements combination */
3294 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02003295 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003296 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003297 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3298 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003299 goto error;
3300 }
3301 } else {
Radek Krejci76512572015-08-04 09:47:08 +02003302 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003303 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003304
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003305 GETVAL(value, sub, "value");
3306 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcifdc0d702017-01-23 15:58:38 +01003307
3308 if (read_yin_subnode_ext(module, rfn, LYEXT_PAR_REFINE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
3309 goto error;
3310 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003311 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02003312 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003313 /* check possibility of statements combination */
3314 if (rfn->target_type) {
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 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003317 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3318 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003319 goto error;
3320 }
3321 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003322 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003323 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003324
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003325 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003326 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003327
Radek Krejci363bd4a2016-07-29 14:30:20 +02003328 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
3329 /* leaf, leaf-list, list, container or anyxml */
3330 /* check possibility of statements combination */
3331 if (rfn->target_type) {
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 if (!rfn->target_type) {
3334 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
3335 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
3336 goto error;
3337 }
3338 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003339 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02003340 }
3341
3342 c_ftrs++;
3343 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003344 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003345 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003346 goto error;
3347 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003348
Michal Vasko345da0a2015-12-02 10:35:55 +01003349 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003350 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003351
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003352 /* process nodes with cardinality of 0..n */
3353 if (c_must) {
3354 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003355 if (!rfn->must) {
3356 LOGMEM;
3357 goto error;
3358 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003359 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02003360 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02003361 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003362 if (!rfn->iffeature) {
3363 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02003364 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003365 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003366 }
Radek Krejci200bf712016-08-16 17:11:04 +02003367 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02003368 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Radek Krejci200bf712016-08-16 17:11:04 +02003369 if (!rfn->dflt) {
3370 LOGMEM;
3371 goto error;
3372 }
3373 }
Radek Krejcie534c132016-11-23 13:32:31 +01003374 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01003375 /* some extensions may be already present from the substatements */
3376 reallocated = realloc(rfn->ext, (c_ext + rfn->ext_size) * sizeof *rfn->ext);
3377 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003378 LOGMEM;
3379 goto error;
3380 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01003381 rfn->ext = reallocated;
3382
3383 /* init memory */
3384 memset(&rfn->ext[rfn->ext_size], 0, c_ext * sizeof *rfn->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01003385 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003386
Radek Krejcie534c132016-11-23 13:32:31 +01003387 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3388 if (strcmp(sub->ns->value, LY_NSYIN)) {
3389 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003390 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 +01003391 rfn->ext_size++;
3392 if (r) {
3393 goto error;
3394 }
3395 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02003396 r = fill_yin_iffeature(uses, 0, sub, &rfn->iffeature[rfn->iffeature_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003397 rfn->iffeature_size++;
3398 if (r) {
3399 goto error;
3400 }
Radek Krejci200bf712016-08-16 17:11:04 +02003401 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01003402 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size], unres);
Radek Krejci363bd4a2016-07-29 14:30:20 +02003403 rfn->must_size++;
3404 if (r) {
3405 goto error;
3406 }
Radek Krejci200bf712016-08-16 17:11:04 +02003407 } else { /* default */
3408 GETVAL(value, sub, "value");
3409
3410 /* check for duplicity */
3411 for (r = 0; r < rfn->dflt_size; r++) {
3412 if (ly_strequal(rfn->dflt[r], value, 1)) {
3413 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3414 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
3415 goto error;
3416 }
3417 }
3418 rfn->dflt[rfn->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02003419 }
3420 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02003421
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003422 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003423
3424error:
3425
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003426 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02003427}
3428
Michal Vasko0d343d12015-08-24 14:57:36 +02003429/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003430static int
Radek Krejcie534c132016-11-23 13:32:31 +01003431fill_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 +02003432{
Radek Krejcie534c132016-11-23 13:32:31 +01003433 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003434 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003435 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003436 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003437
Radek Krejcie534c132016-11-23 13:32:31 +01003438 /* init */
3439 memset(&exts, 0, sizeof exts);
3440
3441 LY_TREE_FOR_SAFE(yin->child, next, child) {
3442 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003443 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003444 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003445 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3446 /* extension */
3447 c_ext++;
3448 lyxml_unlink_elem(module->ctx, child, 2);
3449 lyxml_add_child(module->ctx, &exts, child);
3450 } else if (!strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003451 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01003452 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003453 goto error;
3454 }
3455 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01003456
3457 if (read_yin_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
3458 goto error;
3459 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003460 } else if (!strcmp(child->name, "revision-date")) {
3461 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02003462 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3463 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003464 }
3465 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003466 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003467 goto error;
3468 }
3469 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003470
3471 if (read_yin_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
3472 goto error;
3473 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003474 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003475 if (imp->dsc) {
3476 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3477 goto error;
3478 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003479 if (read_yin_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
3480 goto error;
3481 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003482 imp->dsc = read_yin_subnode(module->ctx, child, "text");
3483 if (!imp->dsc) {
3484 goto error;
3485 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003486 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003487 if (imp->ref) {
3488 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3489 goto error;
3490 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003491 if (read_yin_subnode_ext(module, imp, LYEXT_PAR_IMPORT, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
3492 goto error;
3493 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003494 imp->ref = read_yin_subnode(module->ctx, child, "text");
3495 if (!imp->ref) {
3496 goto error;
3497 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003498 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003499 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003500 goto error;
3501 }
3502 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003503
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003504 /* check mandatory information */
3505 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003506 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003507 goto error;
3508 }
Radek Krejcice7fb782015-05-29 16:52:34 +02003509
Radek Krejcie534c132016-11-23 13:32:31 +01003510 /* process extensions */
3511 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003512 /* some extensions may be already present from the substatements */
3513 reallocated = realloc(imp->ext, (c_ext + imp->ext_size) * sizeof *imp->ext);
3514 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003515 LOGMEM;
3516 goto error;
3517 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003518 imp->ext = reallocated;
3519
3520 /* init memory */
3521 memset(&imp->ext[imp->ext_size], 0, c_ext * sizeof *imp->ext);
3522
Radek Krejcie534c132016-11-23 13:32:31 +01003523 LY_TREE_FOR_SAFE(exts.child, next, child) {
3524 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003525 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 +01003526 imp->ext_size++;
3527 if (r) {
3528 goto error;
3529 }
3530 }
3531 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003532
Radek Krejcie534c132016-11-23 13:32:31 +01003533 GETVAL(value, yin, "module");
Pavol Vicane994fda2016-03-22 10:47:58 +01003534 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02003535
3536error:
3537
Radek Krejcie534c132016-11-23 13:32:31 +01003538 while (exts.child) {
3539 lyxml_free(module->ctx, exts.child);
3540 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003541 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02003542}
3543
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003544/* logs directly
3545 * returns:
3546 * 0 - inc successfully filled
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003547 * -1 - error
Radek Krejci5b2c8a82016-06-17 15:36:03 +02003548 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003549static int
Michal Vasko5ff78822016-02-12 09:33:31 +01003550fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
3551 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02003552{
Radek Krejcie534c132016-11-23 13:32:31 +01003553 struct lyxml_elem *child, *next, exts;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003554 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01003555 int r, c_ext = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01003556 void *reallocated;
Radek Krejciefaeba32015-05-27 14:30:57 +02003557
Radek Krejcie534c132016-11-23 13:32:31 +01003558 /* init */
3559 memset(&exts, 0, sizeof exts);
3560
3561 LY_TREE_FOR_SAFE(yin->child, next, child) {
3562 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003563 /* garbage */
3564 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01003565 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3566 /* extension */
3567 c_ext++;
3568 lyxml_unlink_elem(module->ctx, child, 2);
3569 lyxml_add_child(module->ctx, &exts, child);
3570 } else if (!strcmp(child->name, "revision-date")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003571 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003572 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003573 goto error;
3574 }
3575 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01003576 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003577 goto error;
3578 }
3579 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci95f22ae2017-01-20 14:25:53 +01003580
3581 if (read_yin_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REVISIONDATE, 0, unres)) {
3582 goto error;
3583 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003584 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003585 if (inc->dsc) {
3586 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3587 goto error;
3588 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003589 if (read_yin_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
3590 goto error;
3591 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003592 inc->dsc = read_yin_subnode(module->ctx, child, "text");
3593 if (!inc->dsc) {
3594 goto error;
3595 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02003596 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02003597 if (inc->ref) {
3598 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
3599 goto error;
3600 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003601 if (read_yin_subnode_ext(module, inc, LYEXT_PAR_INCLUDE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
3602 goto error;
3603 }
Michal Vasko8bfe3812016-07-27 13:37:52 +02003604 inc->ref = read_yin_subnode(module->ctx, child, "text");
3605 if (!inc->ref) {
3606 goto error;
3607 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003608 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003609 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003610 goto error;
3611 }
3612 }
Radek Krejciefaeba32015-05-27 14:30:57 +02003613
Radek Krejcie534c132016-11-23 13:32:31 +01003614 /* process extensions */
3615 if (c_ext) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01003616 /* some extensions may be already present from the substatements */
3617 reallocated = realloc(inc->ext, (c_ext + inc->ext_size) * sizeof *inc->ext);
3618 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003619 LOGMEM;
3620 goto error;
3621 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01003622 inc->ext = reallocated;
3623
3624 /* init memory */
3625 memset(&inc->ext[inc->ext_size], 0, c_ext * sizeof *inc->ext);
3626
Radek Krejcie534c132016-11-23 13:32:31 +01003627 LY_TREE_FOR_SAFE(exts.child, next, child) {
3628 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003629 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 +01003630 inc->ext_size++;
3631 if (r) {
3632 goto error;
3633 }
3634 }
3635 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02003636
Radek Krejcie534c132016-11-23 13:32:31 +01003637 GETVAL(value, yin, "module");
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01003638 return lyp_check_include(submodule ? (struct lys_module *)submodule : module, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02003639
3640error:
3641
Radek Krejci83e3f5b2016-06-24 14:55:25 +02003642 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02003643}
3644
Michal Vasko0d343d12015-08-24 14:57:36 +02003645/* logs directly
3646 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003647 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02003648 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02003649 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02003650 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003651static int
Radek Krejci07d0fb92017-01-13 14:11:05 +01003652read_yin_common(struct lys_module *module, struct lys_node *parent, void *stmt, LYEXT_PAR stmt_type,
3653 struct lyxml_elem *xmlnode, int opt, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003654{
Radek Krejci07d0fb92017-01-13 14:11:05 +01003655 struct lys_node *node = stmt;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003656 const char *value;
3657 struct lyxml_elem *sub, *next;
3658 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003659
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003660 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003661 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003662 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003663
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003664 if (opt & OPT_IDENT) {
3665 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01003666 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003667 goto error;
3668 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003669 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003670 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003671
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003672 /* process local parameters */
3673 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003674 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003675 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003676 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02003677 continue;
3678 }
3679 if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejci6ff885d2017-01-03 14:06:22 +01003680 /* possibly an extension, keep the node for later processing, so skipping lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02003681 continue;
3682 }
3683
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003684 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003685 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003686 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003687 goto error;
3688 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003689
Radek Krejciac00b2a2017-01-17 14:05:00 +01003690 if (read_yin_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003691 goto error;
3692 }
3693
Radek Krejci1d82ef62015-08-07 14:44:40 +02003694 node->dsc = read_yin_subnode(ctx, sub, "text");
3695 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003696 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003697 }
3698 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003699 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003700 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003701 goto error;
3702 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003703
Radek Krejciac00b2a2017-01-17 14:05:00 +01003704 if (read_yin_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003705 goto error;
3706 }
3707
Radek Krejci1d82ef62015-08-07 14:44:40 +02003708 node->ref = read_yin_subnode(ctx, sub, "text");
3709 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003710 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003711 }
3712 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003713 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003714 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003715 goto error;
3716 }
3717 GETVAL(value, sub, "value");
3718 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003719 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003720 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003721 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003722 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003723 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003724 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003725 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003726 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003727 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01003728
Radek Krejciac00b2a2017-01-17 14:05:00 +01003729 if (read_yin_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_STATUS, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003730 goto error;
3731 }
Michal Vaskoe022a562016-09-27 14:24:15 +02003732 } else if ((opt & (OPT_CFG_PARSE | OPT_CFG_IGNORE)) && !strcmp(sub->name, "config")) {
3733 if (opt & OPT_CFG_PARSE) {
3734 if (node->flags & LYS_CONFIG_MASK) {
3735 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
3736 goto error;
3737 }
3738 GETVAL(value, sub, "value");
3739 if (!strcmp(value, "false")) {
3740 node->flags |= LYS_CONFIG_R;
3741 } else if (!strcmp(value, "true")) {
3742 node->flags |= LYS_CONFIG_W;
3743 } else {
3744 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3745 goto error;
3746 }
3747 node->flags |= LYS_CONFIG_SET;
Radek Krejci07d0fb92017-01-13 14:11:05 +01003748
Radek Krejciac00b2a2017-01-17 14:05:00 +01003749 if (read_yin_subnode_ext(module, stmt, stmt_type, sub, LYEXT_SUBSTMT_CONFIG, 0, unres)) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01003750 goto error;
3751 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003752 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003753 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003754 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003755 continue;
3756 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003757 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003758 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003759
Michal Vaskoe022a562016-09-27 14:24:15 +02003760 if ((opt & OPT_CFG_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003761 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02003762 if (parent) {
3763 node->flags |= parent->flags & LYS_CONFIG_MASK;
3764 } else if (!parent) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003765 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003766 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003767 }
3768 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003770 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02003771
3772error:
3773
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003774 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003775}
3776
Michal Vasko0d343d12015-08-24 14:57:36 +02003777/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003778static struct lys_when *
Radek Krejci5323b492017-01-16 15:40:11 +01003779read_yin_when(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003780{
Radek Krejci76512572015-08-04 09:47:08 +02003781 struct lys_when *retval = NULL;
Radek Krejci5323b492017-01-16 15:40:11 +01003782 struct lyxml_elem *child, *next;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003783 const char *value;
3784
3785 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01003786 if (!retval) {
3787 LOGMEM;
3788 return NULL;
3789 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003790
3791 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01003792 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02003793 if (!retval->cond) {
3794 goto error;
3795 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003796
Radek Krejci5323b492017-01-16 15:40:11 +01003797 LY_TREE_FOR_SAFE(yin->child, next, child) {
3798 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003799 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003800 continue;
Radek Krejci5323b492017-01-16 15:40:11 +01003801 } else if (strcmp(child->ns->value, LY_NSYIN)) {
3802 /* extensions */
Radek Krejciac00b2a2017-01-17 14:05:00 +01003803 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003804 goto error;
3805 }
3806 } else if (!strcmp(child->name, "description")) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003807 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003808 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003809 goto error;
3810 }
Radek Krejci5323b492017-01-16 15:40:11 +01003811
Radek Krejciac00b2a2017-01-17 14:05:00 +01003812 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003813 goto error;
3814 }
3815
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003816 retval->dsc = read_yin_subnode(module->ctx, child, "text");
3817 if (!retval->dsc) {
3818 goto error;
3819 }
3820 } else if (!strcmp(child->name, "reference")) {
3821 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003822 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003823 goto error;
3824 }
Radek Krejci5323b492017-01-16 15:40:11 +01003825
Radek Krejciac00b2a2017-01-17 14:05:00 +01003826 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_WHEN, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01003827 goto error;
3828 }
3829
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003830 retval->ref = read_yin_subnode(module->ctx, child, "text");
3831 if (!retval->ref) {
3832 goto error;
3833 }
3834 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003835 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003836 goto error;
3837 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003838 }
3839
3840 return retval;
3841
3842error:
3843
Michal Vasko0308dd62015-10-07 09:14:40 +02003844 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003845 return NULL;
3846}
3847
Michal Vasko0d343d12015-08-24 14:57:36 +02003848/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003849static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02003850read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02003851 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02003852{
Michal Vasko29fc0182015-08-24 15:02:39 +02003853 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003854 struct lys_node_case *cs;
3855 struct lys_node *retval, *node = NULL;
Radek Krejcie534c132016-11-23 13:32:31 +01003856 int c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01003857 void *reallocated;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003858
Radek Krejcie867c852015-08-27 09:52:34 +02003859 /* init */
3860 memset(&root, 0, sizeof root);
3861
Radek Krejci1d82ef62015-08-07 14:44:40 +02003862 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01003863 if (!cs) {
3864 LOGMEM;
3865 return NULL;
3866 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003867 cs->nodetype = LYS_CASE;
3868 cs->prev = (struct lys_node *)cs;
3869 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003870
Radek Krejci07d0fb92017-01-13 14:11:05 +01003871 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
3872 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_INHERIT : 0), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003873 goto error;
3874 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003875
Radek Krejcia9544502015-08-14 08:24:29 +02003876 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3877
Michal Vasko3a0043f2015-08-12 12:11:30 +02003878 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003879 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003880 goto error;
3881 }
3882
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003883 /* process choice's specific children */
3884 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01003885 if (strcmp(sub->ns->value, LY_NSYIN)) {
3886 /* extension */
3887 c_ext++;
3888 } else if (!strcmp(sub->name, "container") ||
Michal Vasko29fc0182015-08-24 15:02:39 +02003889 !strcmp(sub->name, "leaf-list") ||
3890 !strcmp(sub->name, "leaf") ||
3891 !strcmp(sub->name, "list") ||
3892 !strcmp(sub->name, "uses") ||
3893 !strcmp(sub->name, "choice") ||
3894 !strcmp(sub->name, "anyxml")) {
3895
Michal Vaskof3930de2015-10-22 12:03:59 +02003896 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02003897 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003898 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02003899 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003900 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003901 if (cs->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003902 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003903 goto error;
3904 }
3905
Radek Krejci5323b492017-01-16 15:40:11 +01003906 cs->when = read_yin_when(module, sub, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02003907 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003908 goto error;
3909 }
Michal Vasko29fc0182015-08-24 15:02:39 +02003910
Michal Vasko345da0a2015-12-02 10:35:55 +01003911 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003912 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01003913 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003914 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003915 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003916 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003917
Radek Krejci3cf9e222015-06-18 11:37:50 +02003918 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003919 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
3920 if (!cs->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003921 LOGMEM;
3922 goto error;
3923 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003924 }
Radek Krejcie534c132016-11-23 13:32:31 +01003925 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01003926 /* some extensions may be already present from the substatements */
3927 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
3928 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01003929 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003930 goto error;
3931 }
Radek Krejci21c81652017-01-23 10:42:55 +01003932 retval->ext = reallocated;
3933
3934 /* init memory */
3935 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003936 }
Radek Krejci21c81652017-01-23 10:42:55 +01003937
Radek Krejcie534c132016-11-23 13:32:31 +01003938 LY_TREE_FOR_SAFE(yin->child, next, sub) {
3939 if (strcmp(sub->ns->value, LY_NSYIN)) {
3940 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01003941 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 +01003942 retval->ext_size++;
3943 if (ret) {
3944 goto error;
3945 }
3946 } else {
3947 /* if-feature */
3948 ret = fill_yin_iffeature(retval, 0, sub, &cs->iffeature[cs->iffeature_size], unres);
3949 cs->iffeature_size++;
3950 if (ret) {
3951 goto error;
3952 }
3953 }
3954 }
Radek Krejcib388c152015-06-04 17:03:03 +02003955
Michal Vasko29fc0182015-08-24 15:02:39 +02003956 /* last part - process data nodes */
3957 LY_TREE_FOR_SAFE(root.child, next, sub) {
3958 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003959 node = read_yin_container(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003960 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003961 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003962 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003963 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003964 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003965 node = read_yin_list(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003966 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003967 node = read_yin_choice(module, retval, sub, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003968 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003969 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003970 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003971 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02003972 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02003973 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003974 }
3975 if (!node) {
3976 goto error;
3977 }
3978
Michal Vasko345da0a2015-12-02 10:35:55 +01003979 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02003980 }
3981
Michal Vasko508a50d2016-09-07 14:50:33 +02003982 /* check XPath dependencies */
3983 if (cs->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3984 goto error;
3985 }
3986
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003987 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003988
3989error:
3990
Michal Vasko29fc0182015-08-24 15:02:39 +02003991 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003992 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02003993 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003994 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02003995
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003996 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003997}
3998
Michal Vasko0d343d12015-08-24 14:57:36 +02003999/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004000static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004001read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
4002 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004003{
Radek Krejci629cdef2016-06-06 15:06:36 +02004004 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004005 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004006 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02004007 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02004008 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01004009 int f_mand = 0, c_ftrs = 0, c_ext = 0, ret;
Radek Krejci21c81652017-01-23 10:42:55 +01004010 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004011
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004012 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01004013 if (!choice) {
4014 LOGMEM;
4015 return NULL;
4016 }
Radek Krejci76512572015-08-04 09:47:08 +02004017 choice->nodetype = LYS_CHOICE;
4018 choice->prev = (struct lys_node *)choice;
4019 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004020
Radek Krejci07d0fb92017-01-13 14:11:05 +01004021 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4022 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004023 goto error;
4024 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004025
Radek Krejcia9544502015-08-14 08:24:29 +02004026 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4027
Michal Vasko3a0043f2015-08-12 12:11:30 +02004028 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004029 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004030 goto error;
4031 }
4032
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004033 /* process choice's specific children */
4034 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004035 if (strcmp(sub->ns->value, LY_NSYIN)) {
4036 /* extension */
4037 c_ext++;
4038 /* keep it for later processing, skip lyxml_free() */
Radek Krejci0d70c372015-07-02 16:23:10 +02004039 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004040 } else if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004041 if (!(node = read_yin_container(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004042 goto error;
4043 }
4044 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004045 if (!(node = read_yin_leaflist(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004046 goto error;
4047 }
4048 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004049 if (!(node = read_yin_leaf(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004050 goto error;
4051 }
4052 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004053 if (!(node = read_yin_list(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004054 goto error;
4055 }
4056 } else if (!strcmp(sub->name, "case")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004057 if (!(node = read_yin_case(module, retval, sub, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004058 goto error;
4059 }
4060 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004061 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres))) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004062 goto error;
4063 }
4064 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004065 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004066 goto error;
4067 }
4068 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02004069 if (dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004070 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004071 goto error;
4072 }
Radek Krejci21c81652017-01-23 10:42:55 +01004073
4074 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
4075 goto error;
4076 }
4077
Radek Krejci629cdef2016-06-06 15:06:36 +02004078 dflt = sub;
4079 lyxml_unlink_elem(ctx, dflt, 0);
Radek Krejcif9a312c2016-06-06 15:14:30 +02004080 continue;
4081 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
4082
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004083 } else if (!strcmp(sub->name, "mandatory")) {
4084 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004085 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004086 goto error;
4087 }
4088 /* just checking the flags in leaf is not sufficient, we would allow
4089 * multiple mandatory statements with the "false" value
4090 */
4091 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02004092
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004093 GETVAL(value, sub, "value");
4094 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004095 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004096 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004097 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004098 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004099 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004100 goto error;
4101 } /* else false is the default value, so we can ignore it */
Radek Krejci21c81652017-01-23 10:42:55 +01004102
4103 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
4104 goto error;
4105 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004106 } else if (!strcmp(sub->name, "when")) {
4107 if (choice->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004108 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004109 goto error;
4110 }
4111
Radek Krejci5323b492017-01-16 15:40:11 +01004112 choice->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004113 if (!choice->when) {
4114 goto error;
4115 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004116 } else if (!strcmp(sub->name, "if-feature")) {
4117 c_ftrs++;
4118
Michal Vasko345da0a2015-12-02 10:35:55 +01004119 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02004120 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02004121 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02004122 if (!(node = read_yin_choice(module, retval, sub, valid_config, unres))) {
Radek Krejci2f792db2016-09-12 10:52:33 +02004123 goto error;
4124 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004125 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004126 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004127 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004128 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004129
Radek Krejci1d82ef62015-08-07 14:44:40 +02004130 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01004131 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004132 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004133
Radek Krejci3cf9e222015-06-18 11:37:50 +02004134 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004135 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
4136 if (!choice->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004137 LOGMEM;
4138 goto error;
4139 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004140 }
Radek Krejcie534c132016-11-23 13:32:31 +01004141 if (c_ext) {
Radek Krejci21c81652017-01-23 10:42:55 +01004142 /* some extensions may be already present from the substatements */
4143 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4144 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004145 LOGMEM;
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004146 goto error;
4147 }
Radek Krejci21c81652017-01-23 10:42:55 +01004148 retval->ext = reallocated;
4149
4150 /* init memory */
4151 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004152 }
4153
Radek Krejcie534c132016-11-23 13:32:31 +01004154 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4155 if (strcmp(sub->ns->value, LY_NSYIN)) {
4156 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004157 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 +01004158 retval->ext_size++;
4159 if (ret) {
4160 goto error;
4161 }
4162 } else {
4163 ret = fill_yin_iffeature(retval, 0, sub, &choice->iffeature[choice->iffeature_size], unres);
4164 choice->iffeature_size++;
4165 if (ret) {
4166 goto error;
4167 }
4168 }
4169 }
4170
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004171 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02004172 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004173 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "default", "choice");
Michal Vasko51e5c582017-01-19 14:16:39 +01004174 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004175 goto error;
4176 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02004177
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004178 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02004179 if (dflt) {
4180 GETVAL(value, dflt, "value");
4181 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004182 goto error;
4183 }
Radek Krejci629cdef2016-06-06 15:06:36 +02004184 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004185 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004186
Michal Vasko508a50d2016-09-07 14:50:33 +02004187 /* check XPath dependencies */
4188 if (choice->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4189 goto error;
4190 }
4191
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004192 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004193
4194error:
4195
Radek Krejci629cdef2016-06-06 15:06:36 +02004196 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004197 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004198
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004199 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004200}
4201
Michal Vasko0d343d12015-08-24 14:57:36 +02004202/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004203static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004204read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type,
4205 int valid_config, struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02004206{
Radek Krejci76512572015-08-04 09:47:08 +02004207 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02004208 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004209 struct lyxml_elem *sub, *next;
4210 const char *value;
4211 int r;
4212 int f_mand = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004213 int c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004214 void *reallocated;
Radek Krejci863c2852015-06-03 15:47:11 +02004215
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004216 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01004217 if (!anyxml) {
4218 LOGMEM;
4219 return NULL;
4220 }
Radek Krejcibf2abff2016-08-23 15:51:52 +02004221 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02004222 anyxml->prev = (struct lys_node *)anyxml;
4223 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02004224
Radek Krejci07d0fb92017-01-13 14:11:05 +01004225 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4226 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004227 goto error;
4228 }
Radek Krejci863c2852015-06-03 15:47:11 +02004229
Radek Krejcia9544502015-08-14 08:24:29 +02004230 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004231
Radek Krejcic189a952016-07-11 15:27:07 +02004232 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004233 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004234 goto error;
4235 }
4236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004237 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004238 if (strcmp(sub->ns->value, LY_NSYIN)) {
4239 /* extension */
4240 c_ext++;
4241 } else if (!strcmp(sub->name, "mandatory")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004242 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004243 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004244 goto error;
4245 }
4246 /* just checking the flags in leaf is not sufficient, we would allow
4247 * multiple mandatory statements with the "false" value
4248 */
4249 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02004250
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004251 GETVAL(value, sub, "value");
4252 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004253 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004254 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004255 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004256 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004257 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004258 goto error;
4259 }
4260 /* else false is the default value, so we can ignore it */
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004261
4262 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
4263 goto error;
4264 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004265 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004266 } else if (!strcmp(sub->name, "when")) {
4267 if (anyxml->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004268 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004269 goto error;
4270 }
4271
Radek Krejci5323b492017-01-16 15:40:11 +01004272 anyxml->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004273 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004274 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004275 goto error;
4276 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004277 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004278 } else if (!strcmp(sub->name, "must")) {
4279 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004280 } else if (!strcmp(sub->name, "if-feature")) {
4281 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02004282
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004283 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004284 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004285 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004286 }
4287 }
Radek Krejci863c2852015-06-03 15:47:11 +02004288
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004289 /* middle part - process nodes with cardinality of 0..n */
4290 if (c_must) {
4291 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004292 if (!anyxml->must) {
4293 LOGMEM;
4294 goto error;
4295 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004296 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004297 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004298 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
4299 if (!anyxml->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004300 LOGMEM;
4301 goto error;
4302 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004303 }
Radek Krejcie534c132016-11-23 13:32:31 +01004304 if (c_ext) {
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004305 /* some extensions may be already present from the substatements */
4306 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4307 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004308 LOGMEM;
4309 goto error;
4310 }
Radek Krejci3a5d9cf2017-01-18 14:06:25 +01004311 retval->ext = reallocated;
4312
4313 /* init memory */
4314 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004315 }
Radek Krejci863c2852015-06-03 15:47:11 +02004316
Radek Krejcie534c132016-11-23 13:32:31 +01004317 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4318 if (strcmp(sub->ns->value, LY_NSYIN)) {
4319 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004320 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 +01004321 retval->ext_size++;
4322 if (r) {
4323 goto error;
4324 }
4325 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004326 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004327 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004328 if (r) {
4329 goto error;
4330 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004331 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004332 r = fill_yin_iffeature(retval, 0, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004333 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004334 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004335 goto error;
4336 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004337 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004338 }
Radek Krejci863c2852015-06-03 15:47:11 +02004339
Michal Vasko508a50d2016-09-07 14:50:33 +02004340 /* check XPath dependencies */
4341 if ((anyxml->when || anyxml->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4342 goto error;
4343 }
4344
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004345 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02004346
4347error:
4348
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004349 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02004350
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004351 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02004352}
4353
Michal Vasko0d343d12015-08-24 14:57:36 +02004354/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004355static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004356read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004357 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004358{
Radek Krejci76512572015-08-04 09:47:08 +02004359 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004360 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004361 struct lyxml_elem *sub, *next;
4362 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01004363 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004364 int c_must = 0, c_ftrs = 0, f_mand = 0, c_ext = 0;
Radek Krejcifccd1442017-01-16 10:26:57 +01004365 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004366
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004367 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01004368 if (!leaf) {
4369 LOGMEM;
4370 return NULL;
4371 }
Radek Krejci76512572015-08-04 09:47:08 +02004372 leaf->nodetype = LYS_LEAF;
4373 leaf->prev = (struct lys_node *)leaf;
4374 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004375
Radek Krejci07d0fb92017-01-13 14:11:05 +01004376 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4377 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004378 goto error;
4379 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004380
Radek Krejcia9544502015-08-14 08:24:29 +02004381 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004382
Radek Krejcic189a952016-07-11 15:27:07 +02004383 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004384 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004385 goto error;
4386 }
4387
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004388 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004389 if (strcmp(sub->ns->value, LY_NSYIN)) {
4390 /* extension */
4391 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004392 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004393 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004394 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004395 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004396 goto error;
4397 }
Michal Vasko88c29542015-11-27 14:57:53 +01004398 /* HACK for unres */
4399 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004400 leaf->type.parent = (struct lys_tpdf *)leaf;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004401 /* postpone type resolution when if-feature parsing is done since we need
4402 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004403 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004404 } else if (!strcmp(sub->name, "default")) {
4405 if (leaf->dflt) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004406 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004407 goto error;
4408 }
4409 GETVAL(value, sub, "value");
4410 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci1abcdae2017-01-18 14:14:18 +01004411
4412 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, 0, unres)) {
4413 goto error;
4414 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004415 } else if (!strcmp(sub->name, "units")) {
4416 if (leaf->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004417 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004418 goto error;
4419 }
4420 GETVAL(value, sub, "name");
4421 leaf->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004422
Radek Krejciac00b2a2017-01-17 14:05:00 +01004423 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004424 goto error;
4425 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004426 } else if (!strcmp(sub->name, "mandatory")) {
4427 if (f_mand) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004428 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004429 goto error;
4430 }
4431 /* just checking the flags in leaf is not sufficient, we would allow
4432 * multiple mandatory statements with the "false" value
4433 */
4434 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02004435
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004436 GETVAL(value, sub, "value");
4437 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004438 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004439 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004440 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02004441 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004442 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004443 goto error;
4444 } /* else false is the default value, so we can ignore it */
Radek Krejcifccd1442017-01-16 10:26:57 +01004445
Radek Krejciac00b2a2017-01-17 14:05:00 +01004446 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MANDATORY, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004447 goto error;
4448 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004449 } else if (!strcmp(sub->name, "when")) {
4450 if (leaf->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004451 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004452 goto error;
4453 }
4454
Radek Krejci5323b492017-01-16 15:40:11 +01004455 leaf->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004456 if (!leaf->when) {
4457 goto error;
4458 }
4459
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004460 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02004461 c_must++;
4462 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004463 } else if (!strcmp(sub->name, "if-feature")) {
4464 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004465 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004466
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004467 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004468 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004469 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004470 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004471
Michal Vasko88c29542015-11-27 14:57:53 +01004472 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004473 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004474
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004475 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004476 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004477 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004478 goto error;
4479 }
Michal Vasko478c4652016-07-21 12:55:01 +02004480 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004481 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "mandatory", "leaf");
Michal Vasko51e5c582017-01-19 14:16:39 +01004482 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL,
Michal Vasko478c4652016-07-21 12:55:01 +02004483 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
4484 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004485 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004486
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004487 /* middle part - process nodes with cardinality of 0..n */
4488 if (c_must) {
4489 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004490 if (!leaf->must) {
4491 LOGMEM;
4492 goto error;
4493 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004494 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004495 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004496 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
4497 if (!leaf->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004498 LOGMEM;
4499 goto error;
4500 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004501 }
Radek Krejcie534c132016-11-23 13:32:31 +01004502 if (c_ext) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004503 /* some extensions may be already present from the substatements */
4504 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4505 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004506 LOGMEM;
4507 goto error;
4508 }
Radek Krejcifccd1442017-01-16 10:26:57 +01004509 retval->ext = reallocated;
4510
4511 /* init memory */
4512 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004513 }
Radek Krejci4c31f122015-06-02 14:51:22 +02004514
Radek Krejcie534c132016-11-23 13:32:31 +01004515 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4516 if (strcmp(sub->ns->value, LY_NSYIN)) {
4517 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004518 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 +01004519 retval->ext_size++;
4520 if (r) {
4521 goto error;
4522 }
4523 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004524 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004525 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004526 if (r) {
4527 goto error;
4528 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004529 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004530 r = fill_yin_iffeature(retval, 0, sub, &leaf->iffeature[leaf->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004531 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004532 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004533 goto error;
4534 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004535 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004536 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004537
Radek Krejcicbb473e2016-09-16 14:48:32 +02004538 /* finalize type parsing */
4539 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
4540 leaf->type.der = NULL;
4541 goto error;
4542 }
4543
4544 /* check default value (if not defined, there still could be some restrictions
4545 * that need to be checked against a default value from a derived type) */
Radek Krejci51673202016-11-01 17:00:32 +01004546 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 +02004547 goto error;
4548 }
4549
Michal Vasko508a50d2016-09-07 14:50:33 +02004550 /* check XPath dependencies */
4551 if ((leaf->when || leaf->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4552 goto error;
4553 }
4554
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004555 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004556
4557error:
4558
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004559 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004560
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004561 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004562}
4563
Michal Vasko0d343d12015-08-24 14:57:36 +02004564/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004565static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004566read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004567 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004568{
Radek Krejci76512572015-08-04 09:47:08 +02004569 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004570 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004571 struct lyxml_elem *sub, *next;
4572 const char *value;
4573 char *endptr;
4574 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004575 int r, has_type = 0;
Radek Krejcie534c132016-11-23 13:32:31 +01004576 int c_must = 0, c_ftrs = 0, c_dflt = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004577 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejci5323b492017-01-16 15:40:11 +01004578 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004579
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004580 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01004581 if (!llist) {
4582 LOGMEM;
4583 return NULL;
4584 }
Radek Krejci76512572015-08-04 09:47:08 +02004585 llist->nodetype = LYS_LEAFLIST;
4586 llist->prev = (struct lys_node *)llist;
4587 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004588
Radek Krejci07d0fb92017-01-13 14:11:05 +01004589 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4590 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004591 goto error;
4592 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004593
Radek Krejcia9544502015-08-14 08:24:29 +02004594 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02004595
Radek Krejcic189a952016-07-11 15:27:07 +02004596 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02004597 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004598 goto error;
4599 }
4600
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004601 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004602 if (strcmp(sub->ns->value, LY_NSYIN)) {
4603 /* extension */
4604 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004605 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01004606 } else if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01004607 if (has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004608 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004609 goto error;
4610 }
Michal Vasko88c29542015-11-27 14:57:53 +01004611 /* HACK for unres */
4612 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01004613 llist->type.parent = (struct lys_tpdf *)llist;
Radek Krejcicbb473e2016-09-16 14:48:32 +02004614 /* postpone type resolution when if-feature parsing is done since we need
4615 * if-feature for check_leafref_features() */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004616 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004617 } else if (!strcmp(sub->name, "units")) {
4618 if (llist->units) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004619 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004620 goto error;
4621 }
4622 GETVAL(value, sub, "name");
4623 llist->units = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci5323b492017-01-16 15:40:11 +01004624
Radek Krejciac00b2a2017-01-17 14:05:00 +01004625 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_UNITS, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004626 goto error;
4627 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004628 } else if (!strcmp(sub->name, "ordered-by")) {
4629 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004630 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004631 goto error;
4632 }
4633 /* just checking the flags in llist is not sufficient, we would
4634 * allow multiple ordered-by statements with the "system" value
4635 */
4636 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004637
Radek Krejci1574a8d2015-08-03 14:16:52 +02004638 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004639 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4640 * state data
4641 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004642 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004643 continue;
4644 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004645
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004646 GETVAL(value, sub, "value");
4647 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004648 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004649 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004650 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004651 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02004652 } /* else system is the default value, so we can ignore it */
4653
Radek Krejciac00b2a2017-01-17 14:05:00 +01004654 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
4655 goto error;
4656 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004657 } else if (!strcmp(sub->name, "must")) {
4658 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02004659 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004660 } else if (!strcmp(sub->name, "if-feature")) {
4661 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004662 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02004663 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
Radek Krejciac00b2a2017-01-17 14:05:00 +01004664 /* read the default's extension instances */
4665 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_DEFAULT, c_dflt, unres)) {
4666 goto error;
4667 }
4668
Radek Krejcid5a5c282016-08-15 15:38:08 +02004669 c_dflt++;
4670 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02004671
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004672 } else if (!strcmp(sub->name, "min-elements")) {
4673 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004674 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004675 goto error;
4676 }
4677 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004678
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004679 GETVAL(value, sub, "value");
4680 while (isspace(value[0])) {
4681 value++;
4682 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004683
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004684 /* convert it to uint32_t */
4685 errno = 0;
4686 endptr = NULL;
4687 val = strtoul(value, &endptr, 10);
4688 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004689 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004690 goto error;
4691 }
4692 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004693 if (llist->max && (llist->min > llist->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004694 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004695 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004696 goto error;
4697 }
Radek Krejci5323b492017-01-16 15:40:11 +01004698
Radek Krejciac00b2a2017-01-17 14:05:00 +01004699 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004700 goto error;
4701 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004702 } else if (!strcmp(sub->name, "max-elements")) {
4703 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004704 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004705 goto error;
4706 }
4707 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004708
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004709 GETVAL(value, sub, "value");
4710 while (isspace(value[0])) {
4711 value++;
4712 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004713
Radek Krejci0d7b2472016-02-12 11:11:03 +01004714 if (!strcmp(value, "unbounded")) {
4715 llist->max = 0;
4716 } else {
4717 /* convert it to uint32_t */
4718 errno = 0;
4719 endptr = NULL;
4720 val = strtoul(value, &endptr, 10);
4721 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004722 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004723 goto error;
4724 }
4725 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004726 if (llist->min > llist->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004727 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01004728 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004729 goto error;
4730 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004731 }
Radek Krejci5323b492017-01-16 15:40:11 +01004732
Radek Krejciac00b2a2017-01-17 14:05:00 +01004733 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
Radek Krejci5323b492017-01-16 15:40:11 +01004734 goto error;
4735 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004736 } else if (!strcmp(sub->name, "when")) {
4737 if (llist->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004738 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004739 goto error;
4740 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004741
Radek Krejci5323b492017-01-16 15:40:11 +01004742 llist->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004743 if (!llist->when) {
4744 goto error;
4745 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004746 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004747 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004748 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004749 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004750
Michal Vasko88c29542015-11-27 14:57:53 +01004751 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004752 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004753
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004754 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004755 if (!has_type) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004756 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004757 goto error;
4758 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004759
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004760 /* middle part - process nodes with cardinality of 0..n */
4761 if (c_must) {
4762 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004763 if (!llist->must) {
4764 LOGMEM;
4765 goto error;
4766 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004767 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004768 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004769 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
4770 if (!llist->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004771 LOGMEM;
4772 goto error;
4773 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004774 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004775 if (c_dflt) {
4776 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
4777 if (!llist->dflt) {
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004778 LOGMEM;
4779 goto error;
4780 }
4781 }
Radek Krejcie534c132016-11-23 13:32:31 +01004782 if (c_ext) {
Radek Krejci5323b492017-01-16 15:40:11 +01004783 /* some extensions may be already present from the substatements */
4784 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
4785 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01004786 LOGMEM;
4787 goto error;
4788 }
Radek Krejci5323b492017-01-16 15:40:11 +01004789 retval->ext = reallocated;
4790
4791 /* init memory */
4792 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01004793 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02004794
Radek Krejcie534c132016-11-23 13:32:31 +01004795 LY_TREE_FOR_SAFE(yin->child, next, sub) {
4796 if (strcmp(sub->ns->value, LY_NSYIN)) {
4797 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01004798 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 +01004799 retval->ext_size++;
4800 if (r) {
4801 goto error;
4802 }
4803 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01004804 r = fill_yin_must(module, sub, &llist->must[llist->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004805 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004806 if (r) {
4807 goto error;
4808 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004809 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02004810 r = fill_yin_iffeature(retval, 0, sub, &llist->iffeature[llist->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004811 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004812 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004813 goto error;
4814 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004815 } else if (!strcmp(sub->name, "default")) {
4816 GETVAL(value, sub, "value");
4817
Radek Krejciac1a52c2016-09-15 14:42:40 +02004818 /* check for duplicity in case of configuration data,
4819 * in case of status data duplicities are allowed */
4820 if (llist->flags & LYS_CONFIG_W) {
4821 for (r = 0; r < llist->dflt_size; r++) {
4822 if (ly_strequal(llist->dflt[r], value, 1)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004823 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, "default");
Michal Vasko51e5c582017-01-19 14:16:39 +01004824 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "Duplicated default value \"%s\".", value);
Radek Krejciac1a52c2016-09-15 14:42:40 +02004825 goto error;
4826 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02004827 }
4828 }
4829 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004830 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004831 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004832
Radek Krejcicbb473e2016-09-16 14:48:32 +02004833 /* finalize type parsing */
4834 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
4835 llist->type.der = NULL;
4836 goto error;
4837 }
4838
Radek Krejcid5a5c282016-08-15 15:38:08 +02004839 if (llist->dflt_size && llist->min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004840 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, retval, "min-elements", "leaf-list");
Michal Vasko51e5c582017-01-19 14:16:39 +01004841 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL,
Radek Krejcid5a5c282016-08-15 15:38:08 +02004842 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
4843 goto error;
4844 }
4845
4846 /* check default value (if not defined, there still could be some restrictions
4847 * that need to be checked against a default value from a derived type) */
4848 for (r = 0; r < llist->dflt_size; r++) {
Radek Krejci51673202016-11-01 17:00:32 +01004849 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
4850 (struct lys_node *)(&llist->dflt[r])) == -1) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02004851 goto error;
Radek Krejci25d782a2015-05-22 15:03:23 +02004852 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004853 }
4854
Michal Vasko508a50d2016-09-07 14:50:33 +02004855 /* check XPath dependencies */
4856 if ((llist->when || llist->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4857 goto error;
4858 }
4859
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004860 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004861
4862error:
4863
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004864 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004865
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004866 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004867}
4868
Michal Vasko0d343d12015-08-24 14:57:36 +02004869/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004870static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02004871read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02004872 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004873{
Radek Krejci1d82ef62015-08-07 14:44:40 +02004874 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02004875 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004876 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01004877 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01004878 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004879 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejci5c08a992016-11-02 13:30:04 +01004880 const char *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004881 char *auxs;
4882 unsigned long val;
Radek Krejcie36d7c72017-01-17 16:12:30 +01004883 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004884
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004885 /* init */
4886 memset(&root, 0, sizeof root);
4887 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02004888
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004889 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01004890 if (!list) {
4891 LOGMEM;
4892 return NULL;
4893 }
Radek Krejci76512572015-08-04 09:47:08 +02004894 list->nodetype = LYS_LIST;
4895 list->prev = (struct lys_node *)list;
4896 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004897
Radek Krejci07d0fb92017-01-13 14:11:05 +01004898 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
4899 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004900 goto error;
4901 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004902
Radek Krejcia9544502015-08-14 08:24:29 +02004903 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4904
Radek Krejcic189a952016-07-11 15:27:07 +02004905 /* insert the node into the schema tree */
4906 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4907 goto error;
4908 }
4909
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004910 /* process list's specific children */
4911 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01004912 if (strcmp(sub->ns->value, LY_NSYIN)) {
4913 /* extension */
4914 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02004915 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02004916
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004917 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01004918 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004919 !strcmp(sub->name, "leaf-list") ||
4920 !strcmp(sub->name, "leaf") ||
4921 !strcmp(sub->name, "list") ||
4922 !strcmp(sub->name, "choice") ||
4923 !strcmp(sub->name, "uses") ||
4924 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004925 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02004926 !strcmp(sub->name, "action") ||
4927 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004928 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004929 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004930
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004931 /* array counters */
4932 } else if (!strcmp(sub->name, "key")) {
4933 /* check cardinality 0..1 */
4934 if (list->keys_size) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004935 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004936 goto error;
4937 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004938
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004939 /* count the number of keys */
4940 GETVAL(value, sub, "value");
Radek Krejci5c08a992016-11-02 13:30:04 +01004941 list->keys_str = lydict_insert(module->ctx, value, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004942 while ((value = strpbrk(value, " \t\n"))) {
4943 list->keys_size++;
4944 while (isspace(*value)) {
4945 value++;
4946 }
4947 }
4948 list->keys_size++;
4949 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01004950 if (!list->keys) {
4951 LOGMEM;
4952 goto error;
4953 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01004954
4955 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_KEY, 0, unres)) {
4956 goto error;
4957 }
4958 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004959 } else if (!strcmp(sub->name, "unique")) {
4960 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02004961 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004962 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004963 } else if (!strcmp(sub->name, "typedef")) {
4964 c_tpdf++;
4965 } else if (!strcmp(sub->name, "must")) {
4966 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004967 } else if (!strcmp(sub->name, "if-feature")) {
4968 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02004969
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004970 /* optional stetments */
4971 } else if (!strcmp(sub->name, "ordered-by")) {
4972 if (f_ordr) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004973 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004974 goto error;
4975 }
4976 /* just checking the flags in llist is not sufficient, we would
4977 * allow multiple ordered-by statements with the "system" value
4978 */
4979 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004980
Radek Krejci1574a8d2015-08-03 14:16:52 +02004981 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004982 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4983 * state data
4984 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004985 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004986 continue;
4987 }
Radek Krejci345ad742015-06-03 11:04:18 +02004988
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004989 GETVAL(value, sub, "value");
4990 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004991 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004992 } else if (strcmp(value, "system")) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01004993 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004994 goto error;
Radek Krejcie36d7c72017-01-17 16:12:30 +01004995 } /* else system is the default value, so we can ignore it */
4996
4997 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_ORDEREDBY, 0, unres)) {
4998 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004999 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005000 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005001 } else if (!strcmp(sub->name, "min-elements")) {
5002 if (f_min) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005003 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005004 goto error;
5005 }
5006 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005007
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005008 GETVAL(value, sub, "value");
5009 while (isspace(value[0])) {
5010 value++;
5011 }
Radek Krejci345ad742015-06-03 11:04:18 +02005012
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005013 /* convert it to uint32_t */
5014 errno = 0;
5015 auxs = NULL;
5016 val = strtoul(value, &auxs, 10);
5017 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005018 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005019 goto error;
5020 }
5021 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005022 if (list->max && (list->min > list->max)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005023 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01005024 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005025 lyxml_free(module->ctx, sub);
5026 goto error;
5027 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005028 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MIN, 0, unres)) {
5029 goto error;
5030 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005031 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005032 } else if (!strcmp(sub->name, "max-elements")) {
5033 if (f_max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005034 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005035 goto error;
5036 }
5037 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02005038
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005039 GETVAL(value, sub, "value");
5040 while (isspace(value[0])) {
5041 value++;
5042 }
Radek Krejci345ad742015-06-03 11:04:18 +02005043
Radek Krejci0d7b2472016-02-12 11:11:03 +01005044 if (!strcmp(value, "unbounded")) {
5045 list->max = 0;;
5046 } else {
5047 /* convert it to uint32_t */
5048 errno = 0;
5049 auxs = NULL;
5050 val = strtoul(value, &auxs, 10);
5051 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005052 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01005053 goto error;
5054 }
5055 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01005056 if (list->min > list->max) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005057 LOGVAL(LYE_INARG, LY_VLOG_LYS, retval, value, sub->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01005058 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01005059 goto error;
5060 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005061 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005062 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_MAX, 0, unres)) {
5063 goto error;
5064 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005065 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005066 } else if (!strcmp(sub->name, "when")) {
5067 if (list->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005068 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005069 goto error;
5070 }
5071
Radek Krejci5323b492017-01-16 15:40:11 +01005072 list->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005073 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005074 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005075 goto error;
5076 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005077 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005078 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005079 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02005080 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005081 }
5082 }
Radek Krejci345ad742015-06-03 11:04:18 +02005083
Michal Vaskoe022a562016-09-27 14:24:15 +02005084 /* check - if list is configuration, key statement is mandatory
5085 * (but only if we are not in a grouping or augment, then the check is deferred) */
5086 for (node = retval; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT)); node = node->parent);
Radek Krejci5c08a992016-11-02 13:30:04 +01005087 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys_str) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005088 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, retval, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005089 goto error;
5090 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005091
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005092 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5093 if (c_tpdf) {
5094 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005095 if (!list->tpdf) {
5096 LOGMEM;
5097 goto error;
5098 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005099 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005100 if (c_must) {
5101 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01005102 if (!list->must) {
5103 LOGMEM;
5104 goto error;
5105 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005106 }
5107 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005108 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
5109 if (!list->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005110 LOGMEM;
5111 goto error;
5112 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005113 }
Radek Krejcie534c132016-11-23 13:32:31 +01005114 if (c_ext) {
Radek Krejcie36d7c72017-01-17 16:12:30 +01005115 /* some extensions may be already present from the substatements */
5116 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5117 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005118 LOGMEM;
5119 goto error;
5120 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005121 retval->ext = reallocated;
5122
5123 /* init memory */
5124 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005125 }
Radek Krejcie36d7c72017-01-17 16:12:30 +01005126
Radek Krejcie534c132016-11-23 13:32:31 +01005127 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5128 if (strcmp(sub->ns->value, LY_NSYIN)) {
5129 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005130 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 +01005131 retval->ext_size++;
5132 if (r) {
5133 goto error;
5134 }
5135 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005136 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
5137 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005138 if (r) {
5139 goto error;
5140 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005141 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005142 r = fill_yin_iffeature(retval, 0, sub, &list->iffeature[list->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005143 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005144 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005145 goto error;
5146 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005147 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005148 r = fill_yin_must(module, sub, &list->must[list->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005149 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005150 if (r) {
5151 goto error;
5152 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005153 }
5154 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005155
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005156 /* last part - process data nodes */
5157 LY_TREE_FOR_SAFE(root.child, next, sub) {
5158 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005159 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005160 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005161 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005162 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005163 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005164 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005165 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005166 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005167 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005168 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005169 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005170 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005171 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005172 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005173 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005174 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005175 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005176 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005177 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005178 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005179 node = read_yin_notif(module, retval, sub, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02005180 } else {
5181 LOGINT;
5182 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005183 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005184 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005185 goto error;
5186 }
Radek Krejci73adb602015-07-02 18:07:40 +02005187
Michal Vasko345da0a2015-12-02 10:35:55 +01005188 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005189 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005190
Radek Krejci5c08a992016-11-02 13:30:04 +01005191 if (list->keys_str) {
5192 /* check that we are not in grouping */
5193 for (node = parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
5194 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01005195 goto error;
5196 }
5197 } /* 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 +02005198
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005199 /* process unique statements */
5200 if (c_uniq) {
5201 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01005202 if (!list->unique) {
5203 LOGMEM;
5204 goto error;
5205 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005206
Radek Krejci461efb92016-02-12 15:52:18 +01005207 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
5208 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
5209 list->unique_size++;
5210 if (r) {
5211 goto error;
5212 }
5213
Radek Krejcie36d7c72017-01-17 16:12:30 +01005214 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub,
5215 LYEXT_SUBSTMT_UNIQUE, list->unique_size - 1, unres)) {
5216 goto error;
5217 }
Radek Krejci461efb92016-02-12 15:52:18 +01005218 lyxml_free(module->ctx, sub);
5219 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005220 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02005221
Michal Vasko508a50d2016-09-07 14:50:33 +02005222 /* check XPath dependencies */
5223 if ((list->when || list->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5224 goto error;
5225 }
5226
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005227 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005228
5229error:
5230
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005231 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005232 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005233 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005234 }
5235 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005236 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005237 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005238
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005239 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005240}
5241
Michal Vasko0d343d12015-08-24 14:57:36 +02005242/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005243static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005244read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02005245 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005246{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005247 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005248 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005249 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005250 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005251 const char *value;
Radek Krejci07d0fb92017-01-13 14:11:05 +01005252 void *reallocated;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005253 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005254 int c_tpdf = 0, c_must = 0, c_ftrs = 0, c_ext = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005255
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005256 /* init */
5257 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005258
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005259 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01005260 if (!cont) {
5261 LOGMEM;
5262 return NULL;
5263 }
Radek Krejci76512572015-08-04 09:47:08 +02005264 cont->nodetype = LYS_CONTAINER;
5265 cont->prev = (struct lys_node *)cont;
5266 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005267
Radek Krejci07d0fb92017-01-13 14:11:05 +01005268 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin,
5269 OPT_IDENT | OPT_MODULE | (valid_config ? OPT_CFG_PARSE | OPT_CFG_INHERIT : OPT_CFG_IGNORE), unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005270 goto error;
5271 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005272
Radek Krejcia9544502015-08-14 08:24:29 +02005273 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5274
Radek Krejcic189a952016-07-11 15:27:07 +02005275 /* insert the node into the schema tree */
5276 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5277 goto error;
5278 }
5279
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005280 /* process container's specific children */
5281 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005282 if (strcmp(sub->ns->value, LY_NSYIN)) {
5283 /* extension */
5284 c_ext++;
5285 } else if (!strcmp(sub->name, "presence")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005286 if (cont->presence) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005287 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005288 goto error;
5289 }
5290 GETVAL(value, sub, "value");
5291 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02005292
Radek Krejciac00b2a2017-01-17 14:05:00 +01005293 if (read_yin_subnode_ext(module, retval, LYEXT_PAR_NODE, sub, LYEXT_SUBSTMT_PRESENCE, 0, unres)) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005294 goto error;
5295 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005296 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005297 } else if (!strcmp(sub->name, "when")) {
5298 if (cont->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005299 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005300 goto error;
5301 }
5302
Radek Krejci5323b492017-01-16 15:40:11 +01005303 cont->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005304 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005305 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005306 goto error;
5307 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005308 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02005309
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005310 /* data statements */
5311 } else if (!strcmp(sub->name, "container") ||
5312 !strcmp(sub->name, "leaf-list") ||
5313 !strcmp(sub->name, "leaf") ||
5314 !strcmp(sub->name, "list") ||
5315 !strcmp(sub->name, "choice") ||
5316 !strcmp(sub->name, "uses") ||
5317 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005318 !strcmp(sub->name, "anyxml") ||
Michal Vaskob4c608c2016-09-15 09:36:20 +02005319 !strcmp(sub->name, "action") ||
5320 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005321 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005322 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005323
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005324 /* array counters */
5325 } else if (!strcmp(sub->name, "typedef")) {
5326 c_tpdf++;
5327 } else if (!strcmp(sub->name, "must")) {
5328 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005329 } else if (!strcmp(sub->name, "if-feature")) {
5330 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005331 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005332 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005333 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005334 }
5335 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005336
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005337 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5338 if (c_tpdf) {
5339 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005340 if (!cont->tpdf) {
5341 LOGMEM;
5342 goto error;
5343 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005344 }
5345 if (c_must) {
5346 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01005347 if (!cont->must) {
5348 LOGMEM;
5349 goto error;
5350 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005351 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005352 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005353 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
5354 if (!cont->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005355 LOGMEM;
5356 goto error;
5357 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005358 }
Radek Krejcie534c132016-11-23 13:32:31 +01005359 if (c_ext) {
Radek Krejci07d0fb92017-01-13 14:11:05 +01005360 /* some extensions may be already present from the substatements */
5361 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5362 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005363 LOGMEM;
5364 goto error;
5365 }
Radek Krejci07d0fb92017-01-13 14:11:05 +01005366 retval->ext = reallocated;
5367
5368 /* init memory */
5369 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005370 }
Radek Krejci800af702015-06-02 13:46:01 +02005371
Radek Krejcie534c132016-11-23 13:32:31 +01005372 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5373 if (strcmp(sub->ns->value, LY_NSYIN)) {
5374 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005375 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 +01005376 retval->ext_size++;
5377 if (r) {
5378 goto error;
5379 }
5380 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005381 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
5382 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005383 if (r) {
5384 goto error;
5385 }
5386 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005387 r = fill_yin_must(module, sub, &cont->must[cont->must_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005388 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005389 if (r) {
5390 goto error;
5391 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005392 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005393 r = fill_yin_iffeature(retval, 0, sub, &cont->iffeature[cont->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005394 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005395 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005396 goto error;
5397 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005398 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005399 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005401 /* last part - process data nodes */
5402 LY_TREE_FOR_SAFE(root.child, next, sub) {
5403 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005404 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005405 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005406 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005407 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005408 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005409 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005410 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005411 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005412 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005413 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005414 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005415 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005416 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005417 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005418 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005419 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005420 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005421 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005422 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vaskob4c608c2016-09-15 09:36:20 +02005423 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005424 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005425 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005426 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005427 goto error;
5428 }
Radek Krejci73adb602015-07-02 18:07:40 +02005429
Michal Vasko345da0a2015-12-02 10:35:55 +01005430 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005431 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005432
Michal Vasko508a50d2016-09-07 14:50:33 +02005433 /* check XPath dependencies */
5434 if ((cont->when || cont->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5435 goto error;
5436 }
5437
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005438 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005439
5440error:
5441
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005442 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005443 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005444 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005445 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005446
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005447 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005448}
5449
Michal Vasko0d343d12015-08-24 14:57:36 +02005450/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005451static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005452read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int valid_config,
Michal Vaskof02e3742015-08-05 16:27:02 +02005453 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005454{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005455 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005456 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005457 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005458 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005459 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005460 int c_tpdf = 0, c_ext = 0;
Radek Krejcifdc0d702017-01-23 15:58:38 +01005461 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005462
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005463 /* init */
5464 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02005465
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005466 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01005467 if (!grp) {
5468 LOGMEM;
5469 return NULL;
5470 }
Radek Krejci76512572015-08-04 09:47:08 +02005471 grp->nodetype = LYS_GROUPING;
5472 grp->prev = (struct lys_node *)grp;
5473 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005474
Radek Krejci07d0fb92017-01-13 14:11:05 +01005475 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE , unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005476 goto error;
5477 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005478
Radek Krejcia9544502015-08-14 08:24:29 +02005479 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5480
Radek Krejcic189a952016-07-11 15:27:07 +02005481 /* insert the node into the schema tree */
5482 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5483 goto error;
5484 }
5485
Radek Krejci1d82ef62015-08-07 14:44:40 +02005486 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005487 if (strcmp(sub->ns->value, LY_NSYIN)) {
5488 /* extension */
5489 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005490
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005491 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005492 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005493 !strcmp(sub->name, "leaf-list") ||
5494 !strcmp(sub->name, "leaf") ||
5495 !strcmp(sub->name, "list") ||
5496 !strcmp(sub->name, "choice") ||
5497 !strcmp(sub->name, "uses") ||
5498 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005499 !strcmp(sub->name, "anyxml") ||
Michal Vasko5acb5482016-09-16 14:35:14 +02005500 !strcmp(sub->name, "action") ||
5501 !strcmp(sub->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005502 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005503 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005504
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005505 /* array counters */
5506 } else if (!strcmp(sub->name, "typedef")) {
5507 c_tpdf++;
5508 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005509 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005510 goto error;
5511 }
5512 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005513
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005514 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5515 if (c_tpdf) {
5516 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005517 if (!grp->tpdf) {
5518 LOGMEM;
5519 goto error;
5520 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005521 }
Radek Krejcie534c132016-11-23 13:32:31 +01005522 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01005523 /* some extensions may be already present from the substatements */
5524 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5525 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005526 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02005527 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005528 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01005529 retval->ext = reallocated;
5530
5531 /* init memory */
5532 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005533 }
Radek Krejcie534c132016-11-23 13:32:31 +01005534 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5535 if (strcmp(sub->ns->value, LY_NSYIN)) {
5536 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005537 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 +01005538 retval->ext_size++;
5539 if (r) {
5540 goto error;
5541 }
5542 } else {
5543 /* typedef */
5544 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
5545 grp->tpdf_size++;
5546 if (r) {
5547 goto error;
5548 }
5549 }
5550 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005551
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005552 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02005553 if (!root.child) {
5554 LOGWRN("Grouping \"%s\" without children.", retval->name);
5555 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005556 LY_TREE_FOR_SAFE(root.child, next, sub) {
5557 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005558 node = read_yin_container(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005559 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005560 node = read_yin_leaflist(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005561 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005562 node = read_yin_leaf(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005563 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005564 node = read_yin_list(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005565 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005566 node = read_yin_choice(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005567 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005568 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005569 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005570 node = read_yin_grouping(module, retval, sub, valid_config, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005571 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005572 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, valid_config, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005573 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005574 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, valid_config, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005575 } else if (!strcmp(sub->name, "action")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005576 node = read_yin_rpc_action(module, retval, sub, unres);
Michal Vasko5acb5482016-09-16 14:35:14 +02005577 } else if (!strcmp(sub->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005578 node = read_yin_notif(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005579 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005580 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005581 goto error;
5582 }
Radek Krejci73adb602015-07-02 18:07:40 +02005583
Michal Vasko345da0a2015-12-02 10:35:55 +01005584 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005585 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005586
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005587 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005588
5589error:
5590
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005591 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005592 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005593 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005594 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005595
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005596 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005597}
5598
Michal Vasko0d343d12015-08-24 14:57:36 +02005599/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005600static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005601read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02005602 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005603{
Radek Krejcie0674f82015-06-15 13:58:51 +02005604 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005605 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02005606 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02005607 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005608 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005609 int c_tpdf = 0, c_must = 0, c_ext = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02005610
Radek Krejcie0674f82015-06-15 13:58:51 +02005611 /* init */
5612 memset(&root, 0, sizeof root);
5613
Michal Vasko38d01f72015-06-15 09:41:06 +02005614 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01005615 if (!inout) {
5616 LOGMEM;
5617 return NULL;
5618 }
Radek Krejci6acc8012015-08-13 09:07:04 +02005619 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02005620
5621 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02005622 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005623 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005624 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02005625 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02005626 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02005627 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02005628 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02005629 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02005630 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005631 }
5632
Radek Krejci76512572015-08-04 09:47:08 +02005633 retval = (struct lys_node *)inout;
Radek Krejcie7770892017-01-24 13:18:01 +01005634 retval->module = module;
Michal Vaskoebeac942015-06-15 12:11:50 +02005635
Radek Krejcia9544502015-08-14 08:24:29 +02005636 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5637
Radek Krejcic189a952016-07-11 15:27:07 +02005638 /* insert the node into the schema tree */
5639 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5640 goto error;
5641 }
5642
Michal Vasko38d01f72015-06-15 09:41:06 +02005643 /* data statements */
5644 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie7770892017-01-24 13:18:01 +01005645 if (!sub->ns) {
5646 /* garbage */
5647 lyxml_free(module->ctx, sub);
5648 } else if (strcmp(sub->ns->value, LY_NSYIN)) {
Radek Krejcie534c132016-11-23 13:32:31 +01005649 /* extension */
5650 c_ext++;
5651 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005652 !strcmp(sub->name, "leaf-list") ||
5653 !strcmp(sub->name, "leaf") ||
5654 !strcmp(sub->name, "list") ||
5655 !strcmp(sub->name, "choice") ||
5656 !strcmp(sub->name, "uses") ||
5657 !strcmp(sub->name, "grouping") ||
5658 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005659 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005660 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005661
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005662 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005663 } else if (!strcmp(sub->name, "typedef")) {
5664 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02005665
Radek Krejci1a31efe2016-07-29 11:04:16 +02005666 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005667 c_must++;
5668
Michal Vasko38d01f72015-06-15 09:41:06 +02005669 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005670 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005671 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005672 }
5673 }
5674
5675 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5676 if (c_tpdf) {
5677 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005678 if (!inout->tpdf) {
5679 LOGMEM;
5680 goto error;
5681 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005682 }
Radek Krejci19332802016-07-29 10:39:46 +02005683 if (c_must) {
5684 inout->must = calloc(c_must, sizeof *inout->must);
5685 if (!inout->must) {
5686 LOGMEM;
5687 goto error;
5688 }
5689 }
Radek Krejcie534c132016-11-23 13:32:31 +01005690 if (c_ext) {
5691 inout->ext = calloc(c_ext, sizeof *inout->ext);
5692 if (!inout->ext) {
5693 LOGMEM;
5694 goto error;
5695 }
5696 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005697
Radek Krejcie534c132016-11-23 13:32:31 +01005698 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5699 if (strcmp(sub->ns->value, LY_NSYIN)) {
5700 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005701 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 +01005702 retval->ext_size++;
5703 if (r) {
5704 goto error;
5705 }
5706 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005707 r = fill_yin_must(module, sub, &inout->must[inout->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02005708 inout->must_size++;
5709 if (r) {
5710 goto error;
5711 }
5712 } else { /* typedef */
5713 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
5714 inout->tpdf_size++;
5715 if (r) {
5716 goto error;
5717 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005718 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005719 }
5720
5721 /* last part - process data nodes */
5722 LY_TREE_FOR_SAFE(root.child, next, sub) {
5723 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005724 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005725 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005726 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005727 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005728 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005729 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005730 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005731 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005732 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005733 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005734 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005735 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005736 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005737 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005738 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005739 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005740 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005741 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005742 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005743 goto error;
5744 }
Radek Krejci73adb602015-07-02 18:07:40 +02005745
Michal Vasko345da0a2015-12-02 10:35:55 +01005746 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005747 }
5748
Michal Vasko508a50d2016-09-07 14:50:33 +02005749 /* check XPath dependencies */
5750 if (inout->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5751 goto error;
5752 }
5753
Michal Vasko38d01f72015-06-15 09:41:06 +02005754 return retval;
5755
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005756error:
Michal Vasko38d01f72015-06-15 09:41:06 +02005757
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005758 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02005759 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005760 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005761 }
5762
5763 return NULL;
5764}
5765
Michal Vasko0d343d12015-08-24 14:57:36 +02005766/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005767static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005768read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +02005769 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02005770{
Michal Vaskoc6551b32015-06-16 10:51:43 +02005771 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005772 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005773 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005774 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005775 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005776 int c_tpdf = 0, c_ftrs = 0, c_must = 0, c_ext = 0;
Radek Krejci478ef1d2017-01-24 13:56:09 +01005777 void *reallocated;
Michal Vasko0ea41032015-06-16 08:53:55 +02005778
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005779 if (parent && (module->version < 2)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005780 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "notification");
Michal Vasko6bb7fc12016-09-21 14:17:22 +02005781 return NULL;
5782 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005783
Michal Vaskoc6551b32015-06-16 10:51:43 +02005784 memset(&root, 0, sizeof root);
5785
Michal Vasko0ea41032015-06-16 08:53:55 +02005786 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01005787 if (!notif) {
5788 LOGMEM;
5789 return NULL;
5790 }
Radek Krejci76512572015-08-04 09:47:08 +02005791 notif->nodetype = LYS_NOTIF;
5792 notif->prev = (struct lys_node *)notif;
5793 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02005794
Radek Krejci07d0fb92017-01-13 14:11:05 +01005795 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005796 goto error;
5797 }
5798
Radek Krejcia9544502015-08-14 08:24:29 +02005799 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5800
Radek Krejcic189a952016-07-11 15:27:07 +02005801 /* insert the node into the schema tree */
5802 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5803 goto error;
5804 }
5805
Michal Vasko0ea41032015-06-16 08:53:55 +02005806 /* process rpc's specific children */
5807 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005808 if (strcmp(sub->ns->value, LY_NSYIN)) {
5809 /* extension */
5810 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02005811 continue;
Radek Krejci0d70c372015-07-02 16:23:10 +02005812
Michal Vasko0ea41032015-06-16 08:53:55 +02005813 /* data statements */
Radek Krejcie534c132016-11-23 13:32:31 +01005814 } else if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005815 !strcmp(sub->name, "leaf-list") ||
5816 !strcmp(sub->name, "leaf") ||
5817 !strcmp(sub->name, "list") ||
5818 !strcmp(sub->name, "choice") ||
5819 !strcmp(sub->name, "uses") ||
5820 !strcmp(sub->name, "grouping") ||
5821 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005822 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005823 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02005824
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005825 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02005826 } else if (!strcmp(sub->name, "typedef")) {
5827 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005828 } else if (!strcmp(sub->name, "if-feature")) {
5829 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02005830 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02005831 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02005832 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005833 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02005834 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02005835 }
5836 }
5837
5838 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5839 if (c_tpdf) {
5840 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005841 if (!notif->tpdf) {
5842 LOGMEM;
5843 goto error;
5844 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005845 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005846 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005847 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
5848 if (!notif->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005849 LOGMEM;
5850 goto error;
5851 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005852 }
Radek Krejci19332802016-07-29 10:39:46 +02005853 if (c_must) {
5854 notif->must = calloc(c_must, sizeof *notif->must);
5855 if (!notif->must) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005856 LOGMEM;
5857 goto error;
5858 }
5859 }
Radek Krejcie534c132016-11-23 13:32:31 +01005860 if (c_ext) {
Radek Krejci478ef1d2017-01-24 13:56:09 +01005861 /* some extensions may be already present from the substatements */
5862 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
5863 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01005864 LOGMEM;
5865 goto error;
5866 }
Radek Krejci478ef1d2017-01-24 13:56:09 +01005867 retval->ext = reallocated;
5868
5869 /* init memory */
5870 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01005871 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005872
Radek Krejcie534c132016-11-23 13:32:31 +01005873 LY_TREE_FOR_SAFE(yin->child, next, sub) {
5874 if (strcmp(sub->ns->value, LY_NSYIN)) {
5875 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01005876 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 +01005877 retval->ext_size++;
5878 if (r) {
5879 goto error;
5880 }
5881 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005882 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
5883 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02005884 if (r) {
5885 goto error;
5886 }
Radek Krejci96299152016-06-22 10:17:50 +02005887 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02005888 r = fill_yin_iffeature(retval, 0, sub, &notif->iffeature[notif->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005889 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005890 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005891 goto error;
5892 }
Radek Krejci19332802016-07-29 10:39:46 +02005893 } else if (!strcmp(sub->name, "must")) {
Radek Krejcifccd1442017-01-16 10:26:57 +01005894 r = fill_yin_must(module, sub, &notif->must[notif->must_size], unres);
Radek Krejci19332802016-07-29 10:39:46 +02005895 notif->must_size++;
Radek Krejci0b24d752015-07-02 15:02:27 +02005896 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005897 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005898 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005899 }
Michal Vasko0ea41032015-06-16 08:53:55 +02005900 }
5901
5902 /* last part - process data nodes */
5903 LY_TREE_FOR_SAFE(root.child, next, sub) {
5904 if (!strcmp(sub->name, "container")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005905 node = read_yin_container(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005906 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005907 node = read_yin_leaflist(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005908 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005909 node = read_yin_leaf(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005910 } else if (!strcmp(sub->name, "list")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005911 node = read_yin_list(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005912 } else if (!strcmp(sub->name, "choice")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005913 node = read_yin_choice(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005914 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005915 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005916 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005917 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005918 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005919 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, 0, unres);
Radek Krejcibf2abff2016-08-23 15:51:52 +02005920 } else if (!strcmp(sub->name, "anydata")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02005921 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, 0, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02005922 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005923 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02005924 goto error;
5925 }
Radek Krejci73adb602015-07-02 18:07:40 +02005926
Michal Vasko345da0a2015-12-02 10:35:55 +01005927 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02005928 }
5929
Michal Vasko508a50d2016-09-07 14:50:33 +02005930 /* check XPath dependencies */
5931 if (notif->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5932 goto error;
5933 }
5934
Michal Vasko0ea41032015-06-16 08:53:55 +02005935 return retval;
5936
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005937error:
Michal Vasko0ea41032015-06-16 08:53:55 +02005938
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005939 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02005940 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005941 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02005942 }
5943
5944 return NULL;
5945}
5946
Michal Vasko0d343d12015-08-24 14:57:36 +02005947/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02005948static struct lys_node *
Michal Vaskoe022a562016-09-27 14:24:15 +02005949read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005950 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02005951{
Radek Krejcie0674f82015-06-15 13:58:51 +02005952 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005953 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02005954 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02005955 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02005956 int r;
Radek Krejcie534c132016-11-23 13:32:31 +01005957 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0, c_ext = 0;
Radek Krejci94596cf2017-01-24 13:19:16 +01005958 void *reallocated;
Michal Vasko38d01f72015-06-15 09:41:06 +02005959
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005960 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02005961 if (module->version < 2) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005962 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, parent, "action");
Michal Vaskobb174852016-07-25 11:00:21 +02005963 return NULL;
5964 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005965 for (node = parent; node; node = lys_parent(node)) {
Radek Krejcia3b19f72016-09-30 13:02:45 +02005966 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005967 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01005968 LOGVAL(LYE_INPAR, LY_VLOG_LYS, parent, strnodetype(node->nodetype), "action");
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005969 return NULL;
5970 }
5971 }
5972 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005973
Radek Krejcie0674f82015-06-15 13:58:51 +02005974 /* init */
5975 memset(&root, 0, sizeof root);
5976
Michal Vasko38d01f72015-06-15 09:41:06 +02005977 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01005978 if (!rpc) {
5979 LOGMEM;
5980 return NULL;
5981 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005982 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02005983 rpc->prev = (struct lys_node *)rpc;
5984 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02005985
Radek Krejci07d0fb92017-01-13 14:11:05 +01005986 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_IDENT | OPT_MODULE, unres)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005987 goto error;
5988 }
5989
Radek Krejcia9544502015-08-14 08:24:29 +02005990 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5991
Radek Krejcic189a952016-07-11 15:27:07 +02005992 /* insert the node into the schema tree */
5993 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5994 goto error;
5995 }
5996
Michal Vasko38d01f72015-06-15 09:41:06 +02005997 /* process rpc's specific children */
5998 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01005999 if (strcmp(sub->ns->value, LY_NSYIN)) {
6000 /* extension */
6001 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006002 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006003 } else if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006004 if (c_input) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006005 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006006 goto error;
6007 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006008 c_input++;
Michal Vaskof3930de2015-10-22 12:03:59 +02006009 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006010 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006011 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02006012 if (c_output) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006013 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006014 goto error;
6015 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02006016 c_output++;
Michal Vaskof3930de2015-10-22 12:03:59 +02006017 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006018 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006019
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006020 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02006021 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02006022 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02006023 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006024
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006025 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02006026 } else if (!strcmp(sub->name, "typedef")) {
6027 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006028 } else if (!strcmp(sub->name, "if-feature")) {
6029 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006030 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006031 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02006032 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02006033 }
6034 }
6035
6036 /* middle part - process nodes with cardinality of 0..n except the data nodes */
6037 if (c_tpdf) {
6038 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01006039 if (!rpc->tpdf) {
6040 LOGMEM;
6041 goto error;
6042 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006043 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006044 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006045 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
6046 if (!rpc->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01006047 LOGMEM;
6048 goto error;
6049 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006050 }
Radek Krejcie534c132016-11-23 13:32:31 +01006051 if (c_ext) {
Radek Krejci94596cf2017-01-24 13:19:16 +01006052 /* some extensions may be already present from the substatements */
6053 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
6054 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01006055 LOGMEM;
6056 goto error;
6057 }
Radek Krejci94596cf2017-01-24 13:19:16 +01006058 retval->ext = reallocated;
6059
6060 /* init memory */
6061 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006062 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006063
Radek Krejcie534c132016-11-23 13:32:31 +01006064 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6065 if (strcmp(sub->ns->value, LY_NSYIN)) {
6066 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006067 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 +01006068 retval->ext_size++;
6069 if (r) {
6070 goto error;
6071 }
6072 } else if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006073 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
6074 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02006075 if (r) {
6076 goto error;
6077 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006078 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006079 r = fill_yin_iffeature(retval, 0, sub, &rpc->iffeature[rpc->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006080 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006081 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006082 goto error;
6083 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006084 }
Michal Vasko38d01f72015-06-15 09:41:06 +02006085 }
6086
6087 /* last part - process data nodes */
6088 LY_TREE_FOR_SAFE(root.child, next, sub) {
6089 if (!strcmp(sub->name, "grouping")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006090 node = read_yin_grouping(module, retval, sub, 0, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02006091 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006092 node = read_yin_input_output(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02006093 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006094 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02006095 goto error;
6096 }
Radek Krejci73adb602015-07-02 18:07:40 +02006097
Michal Vasko345da0a2015-12-02 10:35:55 +01006098 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02006099 }
6100
Michal Vasko38d01f72015-06-15 09:41:06 +02006101 return retval;
6102
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006103error:
Michal Vasko38d01f72015-06-15 09:41:06 +02006104
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006105 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02006106 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006107 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006108 }
6109
6110 return NULL;
6111}
6112
Michal Vasko0d343d12015-08-24 14:57:36 +02006113/* logs directly
6114 *
Radek Krejci74705112015-06-05 10:25:44 +02006115 * resolve - referenced grouping should be bounded to the namespace (resolved)
6116 * only when uses does not appear in grouping. In a case of grouping's uses,
6117 * we just get information but we do not apply augment or refine to it.
6118 */
Radek Krejci76512572015-08-04 09:47:08 +02006119static struct lys_node *
Radek Krejci3440cc52016-06-23 17:03:59 +02006120read_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 +02006121{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006122 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02006123 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02006124 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006125 const char *value;
Radek Krejcie534c132016-11-23 13:32:31 +01006126 int c_ref = 0, c_aug = 0, c_ftrs = 0, c_ext = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006127 int r;
Radek Krejcifdc0d702017-01-23 15:58:38 +01006128 void *reallocated;
Radek Krejci74705112015-06-05 10:25:44 +02006129
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006130 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01006131 if (!uses) {
6132 LOGMEM;
6133 return NULL;
6134 }
Radek Krejci76512572015-08-04 09:47:08 +02006135 uses->nodetype = LYS_USES;
6136 uses->prev = (struct lys_node *)uses;
6137 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02006138
Radek Krejcia9544502015-08-14 08:24:29 +02006139 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006140 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02006141
Radek Krejci07d0fb92017-01-13 14:11:05 +01006142 if (read_yin_common(module, parent, retval, LYEXT_PAR_NODE, yin, OPT_MODULE, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006143 goto error;
6144 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006145
Radek Krejcia9544502015-08-14 08:24:29 +02006146 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
6147
Radek Krejcic189a952016-07-11 15:27:07 +02006148 /* insert the node into the schema tree */
6149 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
6150 goto error;
6151 }
6152
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006153 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02006154 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejcie534c132016-11-23 13:32:31 +01006155 if (strcmp(sub->ns->value, LY_NSYIN)) {
6156 /* extension */
6157 c_ext++;
Radek Krejci0d70c372015-07-02 16:23:10 +02006158 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006159 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006160 c_ref++;
6161 } else if (!strcmp(sub->name, "augment")) {
6162 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006163 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02006164 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006165 } else if (!strcmp(sub->name, "when")) {
6166 if (uses->when) {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006167 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, retval, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006168 goto error;
6169 }
6170
Radek Krejci5323b492017-01-16 15:40:11 +01006171 uses->when = read_yin_when(module, sub, unres);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006172 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006173 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02006174 goto error;
6175 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006176 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006177 } else {
Radek Krejci6f3d6312016-11-04 17:23:18 +01006178 LOGVAL(LYE_INSTMT, LY_VLOG_LYS, retval, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006179 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006180 }
6181 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006182
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006183 /* process properties with cardinality 0..n */
6184 if (c_ref) {
6185 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01006186 if (!uses->refine) {
6187 LOGMEM;
6188 goto error;
6189 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006190 }
6191 if (c_aug) {
6192 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01006193 if (!uses->augment) {
6194 LOGMEM;
6195 goto error;
6196 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006197 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006198 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006199 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
6200 if (!uses->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01006201 LOGMEM;
6202 goto error;
6203 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006204 }
Radek Krejcie534c132016-11-23 13:32:31 +01006205 if (c_ext) {
Radek Krejcifdc0d702017-01-23 15:58:38 +01006206 /* some extensions may be already present from the substatements */
6207 reallocated = realloc(retval->ext, (c_ext + retval->ext_size) * sizeof *retval->ext);
6208 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01006209 LOGMEM;
6210 goto error;
6211 }
Radek Krejcifdc0d702017-01-23 15:58:38 +01006212 retval->ext = reallocated;
6213
6214 /* init memory */
6215 memset(&retval->ext[retval->ext_size], 0, c_ext * sizeof *retval->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006216 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006217
Radek Krejcie534c132016-11-23 13:32:31 +01006218 LY_TREE_FOR_SAFE(yin->child, next, sub) {
6219 if (strcmp(sub->ns->value, LY_NSYIN)) {
6220 /* extension */
Radek Krejci2b999ac2017-01-18 16:22:12 +01006221 r = lyp_yin_fill_ext(retval, LYEXT_PAR_NODE, 0, 0, module, sub, &retval->ext, retval->ext_size, unres);
Radek Krejcie534c132016-11-23 13:32:31 +01006222 retval->ext_size++;
6223 if (r) {
6224 goto error;
6225 }
6226 } else if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02006227 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006228 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006229 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006230 goto error;
6231 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006232 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01006233 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
6234 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02006235 if (r) {
6236 goto error;
6237 }
6238 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci9de2c042016-10-19 16:53:06 +02006239 r = fill_yin_iffeature(retval, 0, sub, &uses->iffeature[uses->iffeature_size], unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +02006240 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01006241 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006242 goto error;
6243 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006244 }
6245 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02006246
Radek Krejci48464ed2016-03-17 15:44:09 +01006247 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02006248 goto error;
6249 }
Radek Krejci74705112015-06-05 10:25:44 +02006250
Michal Vasko508a50d2016-09-07 14:50:33 +02006251 /* check XPath dependencies */
6252 if (uses->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
6253 goto error;
6254 }
6255
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006256 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006257
6258error:
6259
Michal Vaskod51d6ad2016-02-16 13:24:31 +01006260 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006261
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006262 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02006263}
6264
Michal Vasko0d343d12015-08-24 14:57:36 +02006265/* logs directly
6266 *
6267 * common code for yin_read_module() and yin_read_submodule()
6268 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006269static int
Radek Krejcic071c542016-01-27 14:57:51 +01006270read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
6271 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02006272{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006273 struct ly_ctx *ctx = module->ctx;
Radek Krejci95f22ae2017-01-20 14:25:53 +01006274 struct lyxml_elem *next, *child, *next2, *child2, root, grps, augs, exts;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006275 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006276 struct lys_module *trg;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006277 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01006278 int i, r;
Radek Krejcic071c542016-01-27 14:57:51 +01006279 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006280 /* counters */
Radek Krejcie534c132016-11-23 13:32:31 +01006281 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;
6282 int c_ext = 0, c_extinst = 0;
Radek Krejci95f22ae2017-01-20 14:25:53 +01006283 void *reallocated;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006284
Radek Krejcic071c542016-01-27 14:57:51 +01006285 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02006286 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01006287
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006288 /* init */
6289 memset(&root, 0, sizeof root);
6290 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006291 memset(&augs, 0, sizeof augs);
Radek Krejcie534c132016-11-23 13:32:31 +01006292 memset(&exts, 0, sizeof exts);
Radek Krejcie0674f82015-06-15 13:58:51 +02006293
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006294 /*
6295 * in the first run, we process elements with cardinality of 1 or 0..1 and
6296 * count elements with cardinality 0..n. Data elements (choices, containers,
6297 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
6298 * need have all top-level and groupings already prepared at that time. In
6299 * the middle loop, we process other elements with carinality of 0..n since
6300 * we need to allocate arrays to store them.
6301 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006302 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejcie534c132016-11-23 13:32:31 +01006303 if (!child->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02006304 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01006305 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006306 continue;
Radek Krejcie534c132016-11-23 13:32:31 +01006307 } else if (strcmp(child->ns->value, LY_NSYIN)) {
6308 /* possible extension instance */
6309 lyxml_unlink_elem(module->ctx, child, 2);
6310 lyxml_add_child(module->ctx, &exts, child);
6311 c_extinst++;
6312 } else if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006313 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006314 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006315 goto error;
6316 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006317 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006318 module->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006319
6320 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_NAMESPACE, 0, unres)) {
6321 goto error;
6322 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006323 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006324 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006325 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006326 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006327 goto error;
6328 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006329 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01006330 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006331 goto error;
6332 }
6333 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci95f22ae2017-01-20 14:25:53 +01006334
6335 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
6336 goto error;
6337 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006338 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006339 } else if (submodule && !strcmp(child->name, "belongs-to")) {
6340 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006341 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006342 goto error;
6343 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006344 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01006345 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006346 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006347 goto error;
6348 }
Radek Krejcif3886932015-06-04 17:36:06 +02006349
Radek Krejci95f22ae2017-01-20 14:25:53 +01006350 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_BELONGSTO, 0, unres)) {
6351 goto error;
6352 }
6353
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006354 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006355 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006356 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006357 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006358 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006359 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006360 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006361 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006362 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006363 goto error;
6364 }
6365 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006366 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006367 /* check here differs from a generic prefix check, since this prefix
6368 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02006369 */
Radek Krejci48464ed2016-03-17 15:44:09 +01006370 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006371 goto error;
6372 }
Radek Krejcic071c542016-01-27 14:57:51 +01006373 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02006374
Radek Krejci95f22ae2017-01-20 14:25:53 +01006375 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child->child, LYEXT_SUBSTMT_PREFIX, 0, unres)) {
6376 goto error;
6377 }
6378
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006379 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01006380 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02006381
6382 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006383 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006384 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006385 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006386 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006387 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006388 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006389 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006390 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006391 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006392 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02006393 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02006394 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006395 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01006396 lyxml_unlink_elem(ctx, child, 2);
6397 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02006398
Radek Krejci1d82ef62015-08-07 14:44:40 +02006399 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02006400 c_ftrs++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006401
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006402 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006403 } else if (!strcmp(child->name, "container") ||
6404 !strcmp(child->name, "leaf-list") ||
6405 !strcmp(child->name, "leaf") ||
6406 !strcmp(child->name, "list") ||
6407 !strcmp(child->name, "choice") ||
6408 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02006409 !strcmp(child->name, "anyxml") ||
6410 !strcmp(child->name, "rpc") ||
6411 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006412 lyxml_unlink_elem(ctx, child, 2);
6413 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006414
Radek Krejci1d82ef62015-08-07 14:44:40 +02006415 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006416 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01006417 lyxml_unlink_elem(ctx, child, 2);
6418 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006419
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006420 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006421 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006422 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006423 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006424 goto error;
6425 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006426 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
6427 goto error;
6428 }
Radek Krejcic071c542016-01-27 14:57:51 +01006429 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006430 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006431 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006432 goto error;
6433 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006434 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006435 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006436 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006437 goto error;
6438 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006439 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
6440 goto error;
6441 }
Radek Krejcic071c542016-01-27 14:57:51 +01006442 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006443 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006444 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006445 goto error;
6446 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006447 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006448 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006449 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006450 goto error;
6451 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006452 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_ORGANIZATION, 0, unres)) {
6453 goto error;
6454 }
Radek Krejcic071c542016-01-27 14:57:51 +01006455 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006456 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006457 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006458 goto error;
6459 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006460 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006461 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006462 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006463 goto error;
6464 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006465 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_CONTACT, 0, unres)) {
6466 goto error;
6467 }
Radek Krejcic071c542016-01-27 14:57:51 +01006468 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01006469 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01006470 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006471 goto error;
6472 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006473 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006474 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006475 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006476 goto error;
6477 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006478 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02006479 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006480 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006481 goto error;
6482 }
Radek Krejcic071c542016-01-27 14:57:51 +01006483 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02006484 if (!strcmp(value, "1")) {
6485 if (submodule) {
6486 if (module->version > 1) {
6487 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6488 goto error;
6489 }
6490 } else {
6491 module->version = 1;
6492 }
6493 } else {
6494 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02006495 if (module->version < 2) {
Michal Vasko88de3e42016-06-29 11:05:32 +02006496 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6497 goto error;
6498 }
6499 } else {
6500 module->version = 2;
6501 }
6502 }
6503
Radek Krejci95f22ae2017-01-20 14:25:53 +01006504 if (read_yin_subnode_ext(trg, trg, LYEXT_PAR_MODULE, child, LYEXT_SUBSTMT_VERSION, 0, unres)) {
6505 goto error;
6506 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006507 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006508
Radek Krejci1d82ef62015-08-07 14:44:40 +02006509 } else if (!strcmp(child->name, "extension")) {
Radek Krejcia1a6b762016-11-14 09:53:38 +09006510 c_ext++;
Radek Krejci5166a892015-07-02 16:44:24 +02006511
Radek Krejcia1a6b762016-11-14 09:53:38 +09006512 } else if (!strcmp(child->name, "deviation")) {
6513 c_dev++;
6514
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006515 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01006516 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006517 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006518 }
6519 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006520
Radek Krejcic071c542016-01-27 14:57:51 +01006521 /* check for mandatory statements */
Radek Krejci6a1e2f42017-01-19 15:22:00 +01006522 if (submodule) {
6523 if (!submodule->prefix) {
6524 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
6525 goto error;
6526 }
6527 if (!version_flag) {
6528 /* check version compatibility with the main module */
6529 if (module->version > 1) {
6530 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
6531 goto error;
6532 }
6533 }
6534 } else {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006535 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006536 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006537 goto error;
6538 }
6539 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006540 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006541 goto error;
6542 }
6543 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02006544
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006545 /* allocate arrays for elements with cardinality of 0..n */
6546 if (c_imp) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006547 trg->imp = calloc(c_imp, sizeof *trg->imp);
Radek Krejcic071c542016-01-27 14:57:51 +01006548 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01006549 LOGMEM;
6550 goto error;
6551 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006552 }
6553 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006554 trg->rev = calloc(c_rev, sizeof *trg->rev);
6555 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01006556 LOGMEM;
6557 goto error;
6558 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006559 }
6560 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01006561 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
6562 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01006563 LOGMEM;
6564 goto error;
6565 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006566 }
6567 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01006568 trg->ident = calloc(c_ident, sizeof *trg->ident);
6569 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01006570 LOGMEM;
6571 goto error;
6572 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006573 }
6574 if (c_inc) {
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006575 trg->inc = calloc(c_inc, sizeof *trg->inc);
Radek Krejcic071c542016-01-27 14:57:51 +01006576 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01006577 LOGMEM;
6578 goto error;
6579 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006580 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006581 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01006582 trg->augment = calloc(c_aug, sizeof *trg->augment);
6583 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01006584 LOGMEM;
6585 goto error;
6586 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006587 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006588 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01006589 trg->features = calloc(c_ftrs, sizeof *trg->features);
6590 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01006591 LOGMEM;
6592 goto error;
6593 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02006594 }
Radek Krejcieb00f512015-07-01 16:44:58 +02006595 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01006596 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
6597 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01006598 LOGMEM;
6599 goto error;
6600 }
Radek Krejcieb00f512015-07-01 16:44:58 +02006601 }
Radek Krejcia1a6b762016-11-14 09:53:38 +09006602 if (c_ext) {
6603 trg->extensions = calloc(c_ext, sizeof *trg->extensions);
6604 if (!trg->extensions) {
6605 LOGMEM;
6606 goto error;
6607 }
6608 }
Radek Krejcie534c132016-11-23 13:32:31 +01006609 if (c_extinst) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006610 /* some extensions may be already present from the substatements */
6611 reallocated = realloc(trg->ext, (c_extinst + trg->ext_size) * sizeof *trg->ext);
6612 if (!reallocated) {
Radek Krejcie534c132016-11-23 13:32:31 +01006613 LOGMEM;
6614 goto error;
6615 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006616 trg->ext = reallocated;
6617
6618 /* init memory */
6619 memset(&trg->ext[trg->ext_size], 0, c_extinst * sizeof *trg->ext);
Radek Krejcie534c132016-11-23 13:32:31 +01006620 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006621
Michal Vasko2f7925f2015-10-21 15:06:56 +02006622 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
6623 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02006624 if (!strcmp(child->name, "import")) {
Radek Krejcie534c132016-11-23 13:32:31 +01006625 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size], unres);
Radek Krejcic071c542016-01-27 14:57:51 +01006626 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006627 if (r) {
6628 goto error;
6629 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006630
Radek Krejci1d82ef62015-08-07 14:44:40 +02006631 } else if (!strcmp(child->name, "include")) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006632 r = fill_yin_include(trg, submodule, child, &trg->inc[trg->inc_size], unres);
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006633 trg->inc_size++;
6634 if (r) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006635 goto error;
6636 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006637
Radek Krejci1d82ef62015-08-07 14:44:40 +02006638 } else if (!strcmp(child->name, "revision")) {
6639 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01006640 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006641 goto error;
6642 }
Radek Krejcic071c542016-01-27 14:57:51 +01006643 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006644 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01006645 for (i = 0; i < trg->rev_size; i++) {
6646 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006647 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
6648 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006649 }
6650 }
Radek Krejcice7fb782015-05-29 16:52:34 +02006651
Radek Krejci95f22ae2017-01-20 14:25:53 +01006652 LY_TREE_FOR_SAFE(child->child, next2, child2) {
6653 if (!child2->ns) {
6654 /* garbage */
6655 continue;
6656 } else if (strcmp(child2->ns->value, LY_NSYIN)) {
6657 /* possible extension instance */
6658 if (read_yin_subnode_ext(trg, &trg->rev[trg->rev_size], LYEXT_PAR_REVISION,
6659 child2, LYEXT_SUBSTMT_SELF, 0, unres)) {
6660 goto error;
6661 }
6662 } else if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006663 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006664 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006665 goto error;
6666 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006667 if (read_yin_subnode_ext(trg, &trg->rev[trg->rev_size], LYEXT_PAR_REVISION,
6668 child2, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
6669 goto error;
6670 }
Radek Krejcic071c542016-01-27 14:57:51 +01006671 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
6672 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006673 goto error;
6674 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006675 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006676 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006677 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006678 goto error;
6679 }
Radek Krejci95f22ae2017-01-20 14:25:53 +01006680 if (read_yin_subnode_ext(trg, &trg->rev[trg->rev_size], LYEXT_PAR_REVISION,
6681 child2, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
6682 goto error;
6683 }
Radek Krejcic071c542016-01-27 14:57:51 +01006684 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
6685 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006686 goto error;
6687 }
6688 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01006689 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006690 goto error;
6691 }
6692 }
Radek Krejcic071c542016-01-27 14:57:51 +01006693 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02006694
Radek Krejci1d82ef62015-08-07 14:44:40 +02006695 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006696 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
6697 trg->tpdf_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, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006703 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
6704 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006705 if (r) {
6706 goto error;
6707 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006708
Radek Krejci1d82ef62015-08-07 14:44:40 +02006709 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006710 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
6711 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02006712 if (r) {
6713 goto error;
6714 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006715
Radek Krejcia1a6b762016-11-14 09:53:38 +09006716 } else if (!strcmp(child->name, "extension")) {
Radek Krejcie534c132016-11-23 13:32:31 +01006717 r = fill_yin_extension(trg, child, &trg->extensions[trg->extensions_size], unres);
Radek Krejcia1a6b762016-11-14 09:53:38 +09006718 trg->extensions_size++;
6719 if (r) {
6720 goto error;
6721 }
6722
Radek Krejci1d82ef62015-08-07 14:44:40 +02006723 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01006724 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
6725 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02006726 if (r) {
6727 goto error;
6728 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006729 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006730 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02006731
Radek Krejcie534c132016-11-23 13:32:31 +01006732 /* process extension instances */
6733 LY_TREE_FOR_SAFE(exts.child, next, child) {
Radek Krejci95f22ae2017-01-20 14:25:53 +01006734 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 +01006735 trg->ext_size++;
6736 if (r) {
6737 goto error;
6738 }
6739 }
6740
Radek Krejcif5be10f2015-06-16 13:29:36 +02006741 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01006742 * refer to them. Submodule's data nodes are stored in the
6743 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006744 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006745 LY_TREE_FOR_SAFE(grps.child, next, child) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006746 node = read_yin_grouping(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006747 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006748 goto error;
6749 }
Radek Krejci74705112015-06-05 10:25:44 +02006750
Michal Vasko345da0a2015-12-02 10:35:55 +01006751 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006752 }
Radek Krejci74705112015-06-05 10:25:44 +02006753
Radek Krejcif5be10f2015-06-16 13:29:36 +02006754 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02006755 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02006756
Radek Krejci1d82ef62015-08-07 14:44:40 +02006757 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006758 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006759 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006760 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006761 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006762 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006763 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006764 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006765 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01006766 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006767 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02006768 node = read_yin_uses(trg, NULL, child, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02006769 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02006770 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 1, unres);
6771 } else if (!strcmp(child->name, "anydata")) {
6772 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006773 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006774 node = read_yin_rpc_action(trg, NULL, child, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02006775 } else if (!strcmp(child->name, "notification")) {
Michal Vaskoe022a562016-09-27 14:24:15 +02006776 node = read_yin_notif(trg, NULL, child, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006777 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02006778 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006779 goto error;
6780 }
Radek Krejci25d782a2015-05-22 15:03:23 +02006781
Michal Vasko345da0a2015-12-02 10:35:55 +01006782 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006783 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02006784
Michal Vasko2f7925f2015-10-21 15:06:56 +02006785 /* ... and finally augments (last, so we can augment our data, for instance) */
6786 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01006787 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
6788 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02006789
Michal Vasko2f7925f2015-10-21 15:06:56 +02006790 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02006791 goto error;
6792 }
Michal Vasko345da0a2015-12-02 10:35:55 +01006793 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02006794 }
6795
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006796 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02006797
6798error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006799 /* cleanup */
6800 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006801 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006802 }
6803 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006804 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006805 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02006806 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01006807 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02006808 }
Radek Krejcie534c132016-11-23 13:32:31 +01006809 while (exts.child) {
6810 lyxml_free(module->ctx, exts.child);
6811 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006812
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006813 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02006814}
6815
Michal Vasko0d343d12015-08-24 14:57:36 +02006816/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01006817struct lys_submodule *
6818yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02006819{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006820 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01006821 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006822 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02006823
Michal Vasko5a721fd2016-02-16 12:16:48 +01006824 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02006825
Radek Krejci722b0072016-02-01 17:09:45 +01006826 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006827 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01006828 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006829 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006830
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006831 /* check root element */
6832 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01006833 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006834 goto error;
6835 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006836
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006837 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01006838 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006839 goto error;
6840 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006841
Michal Vasko5a721fd2016-02-16 12:16:48 +01006842 submodule = calloc(1, sizeof *submodule);
6843 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006844 LOGMEM;
6845 goto error;
6846 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006847
Michal Vasko5a721fd2016-02-16 12:16:48 +01006848 submodule->ctx = module->ctx;
6849 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
6850 submodule->type = 1;
6851 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02006852
Michal Vasko5a721fd2016-02-16 12:16:48 +01006853 LOGVRB("Reading submodule \"%s\".", submodule->name);
6854 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006855 goto error;
6856 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006857
Radek Krejci33fc4772017-01-26 16:00:35 +01006858 lyp_sort_revisions((struct lys_module *)submodule);
6859
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006860 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01006861 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02006862
Michal Vasko5a721fd2016-02-16 12:16:48 +01006863 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006864 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02006865
6866error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006867 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01006868 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01006869 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01006870
Michal Vasko5a721fd2016-02-16 12:16:48 +01006871 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01006872 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01006873 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01006874 }
6875
Michal Vasko5a721fd2016-02-16 12:16:48 +01006876 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01006877
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006878 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
6879 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006880 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01006881 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02006882}
6883
Michal Vasko0d343d12015-08-24 14:57:36 +02006884/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02006885struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01006886yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02006887{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006888 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01006889 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01006890 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006891 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02006892
Radek Krejcic071c542016-01-27 14:57:51 +01006893 unres = calloc(1, sizeof *unres);
6894 if (!unres) {
6895 LOGMEM;
6896 return NULL;
6897 }
6898
Radek Krejci722b0072016-02-01 17:09:45 +01006899 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006900 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01006901 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006902 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006903
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006904 /* check root element */
6905 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci9a909bd2016-10-24 15:45:51 +02006906 if (ly_strequal("submodule", yin->name, 0)) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01006907 LOGVAL(LYE_SUBMODULE, LY_VLOG_NONE, NULL);
6908 } else {
6909 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci9a909bd2016-10-24 15:45:51 +02006910 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006911 goto error;
6912 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006913
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006914 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01006915 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006916 goto error;
6917 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006918
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006919 module = calloc(1, sizeof *module);
6920 if (!module) {
6921 LOGMEM;
6922 goto error;
6923 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006924
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006925 module->ctx = ctx;
6926 module->name = lydict_insert(ctx, value, strlen(value));
6927 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02006928 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02006929
Michal Vasko9f258e42016-02-11 11:36:27 +01006930 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01006931 if (read_sub_module(module, NULL, yin, unres)) {
6932 goto error;
6933 }
6934
6935 /* resolve rest of unres items */
6936 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006937 goto error;
6938 }
Radek Krejciefaeba32015-05-27 14:30:57 +02006939
Radek Krejci95f22ae2017-01-20 14:25:53 +01006940 lyp_sort_revisions(module);
Radek Krejcibf285832017-01-26 16:05:41 +01006941 lyp_rfn_apply_ext(module);
Radek Krejci95f22ae2017-01-20 14:25:53 +01006942
Radek Krejciff4874d2016-03-07 12:30:50 +01006943 if (revision) {
6944 /* check revision of the parsed model */
6945 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01006946 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
6947 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01006948 goto error;
6949 }
6950 }
6951
Radek Krejcid4c1d0f2017-01-19 16:11:38 +01006952 /* check correctness of includes */
6953 if (lyp_check_include_missing(module)) {
6954 goto error;
6955 }
6956
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006957 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01006958 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006959 }
Radek Krejci63a91a92015-07-29 13:31:04 +02006960
Radek Krejci27fe55e2016-09-13 17:13:35 +02006961 if (module->deviation_size && !module->implemented) {
6962 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
6963 /* deviations always causes target to be made implemented,
6964 * but augents and leafrefs not, so we have to apply them now */
6965 if (lys_set_implemented(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02006966 goto error;
6967 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006968 }
6969
Michal Vasko345da0a2015-12-02 10:35:55 +01006970 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01006971 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01006972 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006973 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006974
6975error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006976 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01006977 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01006978 unres_schema_free(module, &unres);
6979
6980 if (!module) {
Radek Krejci48cfa0f2016-11-08 19:18:34 +01006981 if (ly_vecode != LYVE_SUBMODULE) {
6982 LOGERR(ly_errno, "Module parsing failed.");
6983 }
Radek Krejcib8c07b82016-02-12 11:11:55 +01006984 return NULL;
6985 }
6986
6987 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02006988
Michal Vasko9eb6dd02016-05-02 14:52:40 +02006989 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01006990 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02006991 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02006992}